mirror of
https://github.com/ZDoom/gzdoom-last-svn.git
synced 2025-06-03 10:41:12 +00:00
- Fixed: The players were not added to FS's list of spawned things.
- Update to ZDoom r882 - Added the option to use $ as a prefix to a string table name everywhere in MAPINFO where 'lookup' could be specified so that there is one consistent way to do it. - Externalized all default episode definitions. Added an 'optional' keyword to handle M4 and 5 in Doom and Heretic. - Added P_CheckMapData function and replaced all calls to P_OpenMapData that only checked for a map's presence with it. - Added Martin Howe's player statusbar face submission. - Added an 'adddefaultmap' option for MAPINFO. This is the same as 'defaultmap' but keeps all existing information in the default and just adds to it. This is needed because Hexen and Strife set some information in their base MAPINFO and using 'defaultmap' in a PWAD would override that. - Fixed: Using MAPINFO's f1 option could cause memory leaks. - Added option to load lumps by full name to several places: * Finale texts loaded from a text lump * Demos * Local SNDINFOs * Local SNDSEQs * Image names in FONTDEFS * intermission script names - Changed the STCFN121 handling. The character is not an 'I' but a '|' so instead of discarding it it should be inserted at position 124. - Renamed indexfont.fon to indexfont so that I could remove a special case from V_GetFont that was just added for this one font. - Added a 'dumpspawnedthings' CVAR that enables a listing of all things in the map and the actor type they spawned. SBarInfo Update #16 - Added: fillzeros flag for drawnumber. When set the string will always have a length of the specified size and zeros will fill in for the missing places. If the number is negative the negative sign will take the place of the last digit. - Added: globalarray type to drawnumber which will display the value in a global array with the index set to the player's number. Untested. - Added: isselected command to SBarInfo. - Fixed: Bi and Tri colored numbers didn't work. - Fixed: Crash when using nullimage as the last image in drawswitchableimage. - Applied Graf suggestion to include the y coord when calulating heights to fix most of the gaps caused by round off errors. At least for now anyways and it is only applied for drawimage. - SBarInfo inventory bars have been converted to use screen->DrawTexture() - Increased limit for demon/melee to 4. - Fixed: P_CheckSwitchRange accessed invalid memory when testing a one-sided line. - Fixed: P_SpawnPuff assumed that all melee attacks have the same range (MELEERANGE) and didn't set the puff to its melee state if the range was different. Even worse, it checked a global variable for this so the behavior was undefined when P_SpawnPuff was called from anywhere else but P_LineAttack. To reduce the amount of parameters I combined this information with the hitthing and temporary parameters into one flags parameter. Also changed P_LineAttack so that it gets passed an additional parameter that specifies whether the attack is a melee attack or not and set this to true in all calls that are to be considered melee attacks. I couldn't use the damage type because A_CustomPunch and A_CustomMeleeAttack allow passing any damage type they want. - Added a sprite option as an alternative of particles for FX_ROCKET and FX_GRENADE. - Fixed: The minimum parameter count for ACS_Execute and ACS_ExecuteAlways for DECORATE was wrong (2 instead of 1.) - Changed: Hexen set every cluster to be a hub if it hadn't been defined before a level using this cluster. Now it will only do that if HexenHack is true, i.e. when original Hexen format MAPINFOs are parsed. For ZDoom format MAPINFOs it will now be the same as for the other games which means that 'hub' has to be declared explicitly. - Added an Idle state that is entered in place of the spawn state if a monster has to return to its inactive state if it can't find any more targets. - Added MF5_NOINTERACTION flag which completely disables all physics related code for any actor with this flag. Mostly useful for particle effects where the actors just move a certain distance and then disappear. - Removed the last remains of the antialias precalculation code from am_map.cpp because it was no longer used. - Fixed: Two-sided lines bordering a secret sector were not drawn in the proper color - Fixed: The automap didn't check ACS_LockedExecuteDoor for its lock color. - Switched sounds local to the listener from head-relative 3D sounds to 2D sounds so stereo sounds have full separation. I tried using set3DSpread, but that still caused some blending of the channels. - Changed FScanner so that opening a lump gives the complete wad+lump name rather than a generic one, so identifying errors among files that all have the same lump name no longer involves any degree of guesswork in determining exactly which file the error occurred in. - Added a check to S_ParseSndSeq() for SNDSEQ lumps with unterminated final sequences. - Fixed: Parts of s_sndseq.cpp that scan the Sequences array need NULL pointer checks, in case an improper sequence was encountered during parsing but not early enough to avoid creating a slot for it in the array. - Added support for dumping from RAW/DRO/IMF files, so now anything that can be played as OPL can also be dumped. - Removed the opl_enable cvar, since OPL playback is now selectable as just another MIDI device. - Added support for DRO playback and dual-chip RAW playback. - Removed MUS support from OPLMUSSong, since using the OPLMIDIDevice with MUSSong2 works just as well. There are still lots of leftover bits in the class that should probably be removed at some point, too. - Added dual-chip dumping support for the RAW format. - Added DosBox Raw OPL (.DRO) dumping support. For whatever reason, in_adlib calculates the song length for this format wrong, even though the exact length is stored right in the header. (But in_adlib seems buggy in general; too bad it's the only Windows version of Adplug that seems to exist.) - Rewrote the OPL dumper to work with MIDI as well as MUS. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@86 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
parent
0c2898d332
commit
cabaf17cac
121 changed files with 19530 additions and 18639 deletions
353
docs/rh-log.txt
353
docs/rh-log.txt
|
@ -1,7 +1,350 @@
|
|||
April 5, 2008 (Changes by Graf Zahl)
|
||||
- Added the option to use $ as a prefix to a string table name everywhere in
|
||||
MAPINFO where 'lookup' could be specified so that there is one consistent
|
||||
way to do it.
|
||||
- Externalized all default episode definitions. Added an 'optional' keyword
|
||||
to handle M4 and 5 in Doom and Heretic.
|
||||
- Added P_CheckMapData function and replaced all calls to P_OpenMapData that
|
||||
only checked for a map's presence with it.
|
||||
- Added Martin Howe's player statusbar face submission.
|
||||
- Added an 'adddefaultmap' option for MAPINFO. This is the same as 'defaultmap'
|
||||
but keeps all existing information in the default and just adds to it. This
|
||||
is needed because Hexen and Strife set some information in their base
|
||||
MAPINFO and using 'defaultmap' in a PWAD would override that.
|
||||
- Fixed: Using MAPINFO's f1 option could cause memory leaks.
|
||||
- Added option to load lumps by full name to several places:
|
||||
* Finale texts loaded from a text lump
|
||||
* Demos
|
||||
* Local SNDINFOs
|
||||
* Local SNDSEQs
|
||||
* Image names in FONTDEFS
|
||||
* intermission script names
|
||||
- Changed the STCFN121 handling. The character is not an 'I' but a '|' so
|
||||
instead of discarding it it should be inserted at position 124.
|
||||
- Renamed indexfont.fon to indexfont so that I could remove a special case
|
||||
from V_GetFont that was just added for this one font.
|
||||
- Added a 'dumpspawnedthings' CVAR that enables a listing of all things in
|
||||
the map and the actor type they spawned.
|
||||
|
||||
April 5, 2008 (SBarInfo Update #16)
|
||||
- Added: fillzeros flag for drawnumber. When set the string will always have
|
||||
a length of the specified size and zeros will fill in for the missing places.
|
||||
If the number is negative the negative sign will take the place of the last
|
||||
digit.
|
||||
- Added: globalarray type to drawnumber which will display the value in a
|
||||
global array with the index set to the player's number. Untested.
|
||||
- Added: isselected command to SBarInfo.
|
||||
- Fixed: Bi and Tri colored numbers didn't work.
|
||||
- Fixed: Crash when using nullimage as the last image in drawswitchableimage.
|
||||
- Applied Graf suggestion to include the y coord when calulating heights to fix
|
||||
most of the gaps caused by round off errors. At least for now anyways and it
|
||||
is only applied for drawimage.
|
||||
- SBarInfo inventory bars have been converted to use screen->DrawTexture()
|
||||
|
||||
April 4, 2008 (Changes by Graf Zahl)
|
||||
- Increased limit for demon/melee to 4.
|
||||
- Fixed: P_CheckSwitchRange accessed invalid memory when testing a one-sided
|
||||
line.
|
||||
- Fixed: P_SpawnPuff assumed that all melee attacks have the same range
|
||||
(MELEERANGE) and didn't set the puff to its melee state if the range
|
||||
was different. Even worse, it checked a global variable for this so
|
||||
the behavior was undefined when P_SpawnPuff was called from anywhere
|
||||
else but P_LineAttack. To reduce the amount of parameters I combined
|
||||
this information with the hitthing and temporary parameters into one
|
||||
flags parameter. Also changed P_LineAttack so that it gets passed
|
||||
an additional parameter that specifies whether the attack is a melee
|
||||
attack or not and set this to true in all calls that are to be considered
|
||||
melee attacks. I couldn't use the damage type because A_CustomPunch
|
||||
and A_CustomMeleeAttack allow passing any damage type they want.
|
||||
- Added a sprite option as an alternative of particles for FX_ROCKET
|
||||
and FX_GRENADE.
|
||||
|
||||
April 3, 2008
|
||||
- Changed the Makefiles that are used by both Linux and MinGW so that msys
|
||||
detection occurs only if $OS is Windows_NT. Otherwise, spurious nul files
|
||||
are created when compiling on Linux.
|
||||
|
||||
April 3, 2008 (Changes by Graf Zahl)
|
||||
- Fixed: The minimum parameter count for ACS_Execute and ACS_ExecuteAlways for
|
||||
DECORATE was wrong (2 instead of 1.)
|
||||
|
||||
April 2, 2008 (Changes by Graf Zahl)
|
||||
- Changed: Hexen set every cluster to be a hub if it hadn't been defined before
|
||||
a level using this cluster. Now it will only do that if HexenHack is true,
|
||||
i.e. when original Hexen format MAPINFOs are parsed. For ZDoom format
|
||||
MAPINFOs it will now be the same as for the other games which means that
|
||||
'hub' has to be declared explicitly.
|
||||
- Added an Idle state that is entered in place of the spawn state if a monster
|
||||
has to return to its inactive state if it can't find any more targets.
|
||||
- Added MF5_NOINTERACTION flag which completely disables all physics related
|
||||
code for any actor with this flag. Mostly useful for particle effects where
|
||||
the actors just move a certain distance and then disappear.
|
||||
- Removed the last remains of the antialias precalculation code from
|
||||
am_map.cpp because it was no longer used.
|
||||
- Fixed: Two-sided lines bordering a secret sector were not drawn in the
|
||||
proper color
|
||||
- Fixed: The automap didn't check ACS_LockedExecuteDoor for its lock color.
|
||||
|
||||
April 2, 2008
|
||||
- Switched sounds local to the listener from head-relative 3D sounds to 2D
|
||||
sounds so stereo sounds have full separation. I tried using set3DSpread,
|
||||
but that still caused some blending of the channels.
|
||||
- Changed FScanner so that opening a lump gives the complete wad+lump name
|
||||
rather than a generic one, so identifying errors among files that all have
|
||||
the same lump name no longer involves any degree of guesswork in
|
||||
determining exactly which file the error occurred in.
|
||||
- Added a check to S_ParseSndSeq() for SNDSEQ lumps with unterminated final
|
||||
sequences.
|
||||
- Fixed: Parts of s_sndseq.cpp that scan the Sequences array need NULL
|
||||
pointer checks, in case an improper sequence was encountered during
|
||||
parsing but not early enough to avoid creating a slot for it in the array.
|
||||
- Added support for dumping from RAW/DRO/IMF files, so now anything that
|
||||
can be played as OPL can also be dumped.
|
||||
- Removed the opl_enable cvar, since OPL playback is now selectable as just
|
||||
another MIDI device.
|
||||
|
||||
April 1, 2008
|
||||
- Added support for DRO playback and dual-chip RAW playback.
|
||||
|
||||
March 30, 2008
|
||||
- Removed MUS support from OPLMUSSong, since using the OPLMIDIDevice with
|
||||
MUSSong2 works just as well. There are still lots of leftover bits in
|
||||
the class that should probably be removed at some point, too.
|
||||
- Added dual-chip dumping support for the RAW format.
|
||||
- Added DosBox Raw OPL (.DRO) dumping support. For whatever reason,
|
||||
in_adlib calculates the song length for this format wrong, even though
|
||||
the exact length is stored right in the header. (But in_adlib seems buggy
|
||||
in general; too bad it's the only Windows version of Adplug that seems to
|
||||
exist.)
|
||||
- Rewrote the OPL dumper to work with MIDI as well as MUS.
|
||||
|
||||
March 30, 2008 (Changes by Graf Zahl)
|
||||
- Changed: When the screen is being deleted the 'screen' variable should be
|
||||
set to NULL before performing the delete. Otherwise, in some abnormal
|
||||
situations, it could happen that the destroyed screen object is still
|
||||
being accessed.
|
||||
- Fixed: V_Shutdown didn't set OF_YesReallyDelete before deleting screen.
|
||||
- Fixed: The HIRESTEX parser didn't check if a graphic specified in a remap
|
||||
command actually existed.
|
||||
- Fixed: My $Limit fix from yesterday didn't work because NearLimit was
|
||||
an unsigned byte and the comparisons with -1 didn't work. Made it a
|
||||
signed word instead.
|
||||
- Made sfxinfo_t::Link an unsigned int because it limited the amount of
|
||||
usable sounds to 65535.
|
||||
|
||||
March 29, 2008
|
||||
- Fixed: OPLMIDIDevice sent the wrong pitch wheel value to the player code.
|
||||
Missimp.mid sounds a lot better now, though still a little off.
|
||||
- Fixed: MIDI files that had ticks with nothing but meta-events did not play
|
||||
properly. (fixes sonic3_finalboss.mid)
|
||||
- Applied Const's Makefile.linux changes.
|
||||
- Made the OPL MIDI synth available from Linux.
|
||||
|
||||
March 29, 2008 (Changes by Graf Zahl)
|
||||
- Added SnowKate709's A_DamageMaster/A_DamageChildren patch.
|
||||
- Added a SFX_TRANSFERAMBUSHFLAG for A_SpawnItemEx.
|
||||
- Added "Shaded" as a valid parameter for DECORATE's RenderStyle.
|
||||
- Added Karate Chris's patch for a MAPINFO option making Strife conversations
|
||||
not halt the game.
|
||||
- Extended the $limit fix that $alias and $random definitions can have their
|
||||
own $limit now.
|
||||
- Fixed: When resolving a linked sound the limit of the current sound was
|
||||
ignored and the one of the referenced sound being used. This was particularly
|
||||
noticable when using the chaingun in a group of Zombiemen.
|
||||
- Added a namespc parameter to FWadCollection::CheckNumForFullName which is
|
||||
used when a normal lump name has to be looked up and changed all
|
||||
CheckNumForFullName/CheckNumForName combinations in the source to use
|
||||
the extended version of CheckNumForFullName only to have consistent
|
||||
behavior for lump name lookup.
|
||||
|
||||
March 28, 2008
|
||||
- Moved sound sample rate, buffer size, and buffer count to the
|
||||
advanced sound options menu. Removed opl_enable from the menu.
|
||||
- Added OPL synth as MIDI device -3. Since this is based on the MUS player
|
||||
code, it only supports those events and controllers supported by MUS.
|
||||
Some of Duke's MIDIs sound awful, but I think that may be more because
|
||||
it's using different instruments... There's a thread in the MIDI streamer
|
||||
class that could be taken out for Linux, since it doesn't need to deal
|
||||
with the Windows Multimedia API, but for now, this is still Windows-only.
|
||||
- Changed the output of the OPL emulator from 32-bit integers to 32-bit
|
||||
floats, so I can write its output directly to the stream buffer. In
|
||||
addition, this lets me bring the OPL volume level much closer to the
|
||||
standard MIDI volume.
|
||||
|
||||
March 27, 2008
|
||||
- Did some restructuring of the OPL code in preparation for turning it
|
||||
into a general MIDI player.
|
||||
- Fixed: Passing false for a stream callback did not stop the stream.
|
||||
- Removed opl_frequency, since the only time the emulation sounds good is
|
||||
when it plays at the exact frequency of a real chip.
|
||||
- Music no longer plays at all when snd_musicvolume is 0.
|
||||
- Bumped up snd_sfxvolume and snd_musicvolume default values.
|
||||
- Changed D3DFB to explicitly request double buffering instead of assuming
|
||||
that the drivers will treat a BackBufferCount of 0 as a request for
|
||||
double buffering.
|
||||
- Fixed: Unsetting a cvar did not remove it from the list of tab
|
||||
completions.
|
||||
- Added "" as a synonym for "nullimage" in SBARINFO.
|
||||
- Fixed: MAKESAVESIG's stringifier in version.h did not work as expected.
|
||||
It stringified the passed macro name, not the value of the macro.
|
||||
- Moved DCajunMaster off the DObject hierarchy.
|
||||
- Changed DCajunMaster::getspawned into a TArray of FStrings. It was
|
||||
mysteriously being left pointing to uninitialized memory during the
|
||||
final GC at exit and crashing.
|
||||
- Fixed: The code that removed hexdd.wad from the list of IWADs when
|
||||
hexen.wad was not present did not work.
|
||||
|
||||
March 27, 2008 (Changes by Graf Zahl)
|
||||
- Fixed: DCajunMaster::End was missing a write barrier for getspawned. The
|
||||
same problem in D_DoomMain.
|
||||
- Made bglobal a pointer because it was causing problems with the garbage
|
||||
collector.
|
||||
|
||||
March 26, 2008
|
||||
- Added uppercase copies of the IWAD names to the IWAD search for Unix land.
|
||||
- Added FMOD_OPENONLY to the callback version of CreateStream() to prevent it
|
||||
from doing prebuffering of the song. This was causing the Linux version to
|
||||
hang while waiting for input from the pipe, since Timidity hadn't been
|
||||
started yet. I tried using a select call in the FillStream() method, but it
|
||||
always seems to return the pipe as having nothing available. Unfortunately,
|
||||
the game still falls all over itself if Timidity isn't available. Instead
|
||||
of execvp failing nicely, X errors kill the game. I don't know why it's
|
||||
doing that. My advice for Linux music: Skip Timidity++ and get a DLS patch
|
||||
set (/WINDOWS/system32/drivers/gm.dls is probably the most common by far)
|
||||
and set the snd_midipatchset cvar to point to it. It's faster and also
|
||||
sounds a whole lot better than the crappy freepats Ubuntu wants to install
|
||||
with Timidity++ (thank goodness I have the official patches from a real
|
||||
GUS so I don't need to use them).
|
||||
- GCC fixes.
|
||||
|
||||
March 26, 2008 (Changes by Graf Zahl)
|
||||
- Fixed: After starting new music the music volume has to be reset so that
|
||||
the song's relative volume takes effect.
|
||||
- Removed the arbitrary 1024 bytes limit when the file being played is a MIDI
|
||||
file. I had a D_DM2TTL that's only 990 bytes.
|
||||
- Restructured I_RegisterSong so that $mididevice works again and also supports
|
||||
selecting FMOD.
|
||||
- Added Jim' Linux fix.
|
||||
- Added MartinHowe's fix for mugshot display in status bars.
|
||||
|
||||
March 25, 2008
|
||||
- The garbage collector is now run one last time just before exiting the game.
|
||||
- Removed movie volume from the sound menu and renamed some of the other
|
||||
options to give the MIDI device name more room to display itself.
|
||||
- Moved the midi device selection into the main sound menu.
|
||||
- Added FMOD as MIDI device -1, to replace the MIDI mapper. This is still the
|
||||
default device. By default, it uses exactly the same DLS instruments as the
|
||||
Microsoft GS Wavetable Synth. If you have another set DLS level 1 patch set
|
||||
you want to use, set the snd_midipatchset cvar to specify where it should
|
||||
load the instruments from.
|
||||
- Changed the ProduceMIDI function to store its output into a TArray<BYTE>.
|
||||
An overloaded version wraps around it to continue to supply file-writing
|
||||
support for external Timidity++ usage.
|
||||
- Added an FMOD credits banner to comply with their non-commercial license.
|
||||
- Reimplemented the snd_buffersize cvar for the FMOD Ex sound system. Rather
|
||||
than a time in ms, this is now the length in samples of the DSP buffer.
|
||||
Also added the snd_buffercount cvar to offer complete control over the
|
||||
call to FMOD::System::setDSPBufferSize(). Note that with any snd_samplerate
|
||||
below about 44kHz, you will need to set snd_buffersize to avoid long
|
||||
latencies.
|
||||
- Reimplemented the snd_output cvar for the FMOD Ex sound system.
|
||||
- Changed snd_samplerate default to 0. This now means to use the default
|
||||
sample rate.
|
||||
- Made snd_output, snd_output_format, snd_speakermode, snd_resampler, and
|
||||
snd_hrtf available through the menu.
|
||||
- Split the HRTF effect selection into its own cvar: snd_hrtf.
|
||||
- Removed 96000 Hz option from the menu. It's still available through the
|
||||
cvar, if desired.
|
||||
- Fixed: If Windows sound init failed, retry with DirectSound. (Apparently,
|
||||
WASAPI doesn't work with more than two speakers and PCM-Float output at the
|
||||
same time.)
|
||||
- Fixed: Area sounds only played from the front speakers once you got within
|
||||
the 2D panning area.
|
||||
|
||||
March 25, 2008 (Changes by Graf Zahl)
|
||||
- Added Karate Chris's submission for multiplayer Strife conversations.
|
||||
- Increased the limit for 'imp/active' to 6. This sound definitely benefits
|
||||
from a higher limit.
|
||||
- Fixed: $limit should not apply to sounds played from the menu.
|
||||
- Fixed: The SNDSEQ parser tried to set bDoorSound before actually creating
|
||||
the sound sequence data.
|
||||
- Changed Lemon so that it always writes the header. It still kept recompiling
|
||||
the grammar over and over again once it had been changed locally.
|
||||
- Fixed: ANIMATED allowed animations between different texture types.
|
||||
- Added a debuganimated CCMD that can be used to output some information
|
||||
if a WAD shows broken animations.
|
||||
|
||||
March 24, 2008
|
||||
- Removed xlat_parser.h from the repository. Lemon was always being run on
|
||||
xlat_parser.y because both files had the same time stamp after an update,
|
||||
and Lemon only rewrites the header file if it's changed.
|
||||
- Added $volume SNDINFO command. This is multiplied with the volume the sound
|
||||
is played at to arrive at the final volume (before distance attenuation).
|
||||
- Added the CHAN_AREA flag to disable 3D panning within the min distance of a
|
||||
sound. Sector sound sequences (except doors) use this flag.
|
||||
- Added the CHAN_LOOP flag to replace the S_Looped* sound functions.
|
||||
- Restored the sound limiting.
|
||||
|
||||
March 24, 2008 (Changes by Graf Zahl)
|
||||
- Fixed: THe handling for enum values in Xlat was incorrect. The rule with
|
||||
value assignment must set the counter one higher than the current value.
|
||||
- Fixed: The definition of enums in the Xlat grammar was right-recursive
|
||||
which could create stack overflows in the parser. Made it left-recursive as
|
||||
recommended in Lemon's docs.
|
||||
- Added Thomas's submissions for decal assignment to puffs and NOINFIGHTING flag.
|
||||
- Reverted changes of r715 in v_collection.cpp because they broke loading
|
||||
of status bar face graphics belonging to skins.
|
||||
SBARINFO update #15
|
||||
- Fixed: Monospacing fonts wasn't quite correct.
|
||||
- Fixed: The new mug shot code forgot to use the first arg of drawmugshot (the
|
||||
one that picks the default sprite prefix).
|
||||
- Added: lowerHealthCap variable to SBarInfo, which is set to true by default.
|
||||
- Added: ininventory event to SBarInfo to detect if one or two items are in (or
|
||||
not in) the player's inventory.
|
||||
- Added: The ability to print global vars using drawnumber. I need someone to
|
||||
test it though.
|
||||
- Added: aspectratio command to detect what the user's aspect ratio is.
|
||||
- Added: missing spacing argument to drawstring.
|
||||
- Changed the sbarinfo display routine for drawnumber to not use cmd.value to
|
||||
store what it is about to display. Now it uses a new variable.
|
||||
- More conversions from DrawImage to screen->DrawTexture. I think only the
|
||||
inventory bar drawing functions have to be changed now.
|
||||
|
||||
March 23, 2008 (Changes by Graf Zahl)
|
||||
- Fixed: The Sequence pointer in ASoundSequenceSlot was not declared as
|
||||
a pointer and it was missing both read and write barriers.
|
||||
- Fixed: The sector translators must clear unused bits because they might
|
||||
render a sector's special inoperable.
|
||||
- Expanded the args for MAPINFO special actions to 32 bit integers as in
|
||||
the rest of the game.
|
||||
- Fixed: The specialaction list was not copied properly when transferred
|
||||
from the defaultinfo.
|
||||
- Fixed: The defaultinfo for MAPINFO wasn't cleared fully after MAPINFO
|
||||
parsing was completed.
|
||||
- Made Doom-format linedef translators a map property so that it's easier
|
||||
to define replacements or extensions.
|
||||
|
||||
March 22, 2008
|
||||
- Changed MIDI playback to not bother playing super short songs that don't
|
||||
contain enough music to fill the initial output buffers.
|
||||
- Removed the read barrier around ADehackedPickup::RealPickup. If the real
|
||||
pickup is picked up, it may very well destroy itself before the dehacked
|
||||
wrapper's stubs that use it are called.
|
||||
- Reverted revision 840. For a file we don't want end users to be touching,
|
||||
making DEHSUPP plain text sends out mixed messages: "Don't mess with this.
|
||||
Oh, by the way, it's plain text now to make it easier for you to edit."
|
||||
Is there some reason other than a desire to do away with binary lumps to
|
||||
make the distributed lump text?
|
||||
- Added a new speakermode for Stereo + HRTF: "Headphones". This is the only
|
||||
way to get the HRTF low pass filter effect now.
|
||||
- Fixed: No more than one sector could make noise at once.
|
||||
- Trying out sound without varying priorities again.
|
||||
- Fixed: Need to use setSpeakerMix to let 2D sounds (aka streamed music) use
|
||||
their full volume range.
|
||||
|
||||
March 22, 2008 (Changes by Graf Zahl)
|
||||
- Changed DEHSUPP loader so that it reads the text file directly. As a result
|
||||
the DEHSUPP compiler is gone now. Unlike XLATCC I'm using FScanner though.
|
||||
A fully featured parser seems like overkill for this simple text file.
|
||||
- Added sector type translation to xlat_parser and removed the old sectorx
|
||||
lump.
|
||||
- Added Line_SetTextureOffset special.
|
||||
- Added 'allowprotection' keyword to terrain definitions to allow damaging
|
||||
flats that don't damage players with a radiation suit.
|
||||
|
@ -418,7 +761,7 @@ February 26, 2008
|
|||
- More write barriers and pointer declarations. Here are rules I've come up
|
||||
with so far for when write barriers can be ommitted:
|
||||
* Initializing pointers for a newly created object: A new object can never
|
||||
black, so none of its pointers that get set by the constructor (or code
|
||||
be black, so none of its pointers that get set by the constructor (or code
|
||||
just following its creation) need to be behind write barriers.
|
||||
* Creating a new thinker and storing it in a pointer: The thinker
|
||||
constructor already puts it behind a write barrier when it links it into
|
||||
|
@ -5681,7 +6024,7 @@ February 9, 2005
|
|||
took me a while to figure out the problem, ZDoom can now play raw OPL songs.
|
||||
|
||||
February 7, 2005
|
||||
- Added the writeopl command to write a song in RDosPlay raw OPL format. It's usage is:
|
||||
- Added the writeopl command to write a song in RDosPlay raw OPL format. Its usage is:
|
||||
writeopl [songname] <filename>
|
||||
If the currently playing song is a MUS song being played through the OPL emulation,
|
||||
then you just need to specify the filename. Otherwise, you need to provide the
|
||||
|
|
|
@ -2860,6 +2860,10 @@
|
|||
RelativePath=".\src\oplsynth\music_opl_mididevice.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\oplsynth\music_opldumper_mididevice.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="src\sound\music_spc.cpp"
|
||||
>
|
||||
|
@ -2903,10 +2907,6 @@
|
|||
RelativePath=".\src\oplsynth\fmopl.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\oplsynth\mlkernel.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\oplsynth\mlopl.cpp"
|
||||
>
|
||||
|
|
|
@ -33,7 +33,7 @@ $(STATICLIB): $(OBJS)
|
|||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
ifeq (msys,$(OSTYPE))
|
||||
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||
rm -f $(STATICLIB)
|
||||
rm -f *.o
|
||||
else
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
# Makefile for snes_spc, derived from zlib/Makefile.mgw.
|
||||
|
||||
CMD=0
|
||||
ifeq (Windows_NT,$(OS))
|
||||
CMD=1
|
||||
endif
|
||||
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||
CMD=0
|
||||
endif
|
||||
endif
|
||||
|
||||
STATICLIB = libsnes_spc.a
|
||||
|
|
|
@ -72,7 +72,7 @@ DEFINE_SPECIAL(TeleportOther, 76, 3, 3)
|
|||
DEFINE_SPECIAL(TeleportGroup, 77, 5, 5)
|
||||
DEFINE_SPECIAL(TeleportInSector, 78, 4, 5)
|
||||
|
||||
DEFINE_SPECIAL(ACS_Execute, 80, 2, 5)
|
||||
DEFINE_SPECIAL(ACS_Execute, 80, 1, 5)
|
||||
DEFINE_SPECIAL(ACS_Suspend, 81, 2, 2)
|
||||
DEFINE_SPECIAL(ACS_Terminate, 82, 2, 2)
|
||||
DEFINE_SPECIAL(ACS_LockedExecute, 83, 5, 5)
|
||||
|
@ -197,7 +197,7 @@ DEFINE_SPECIAL(Scroll_Texture_Model, 222, -1, -1)
|
|||
DEFINE_SPECIAL(Scroll_Floor, 223, 4, 4)
|
||||
DEFINE_SPECIAL(Scroll_Ceiling, 224, 4, 4)
|
||||
DEFINE_SPECIAL(Scroll_Texture_Offsets, 225, -1, -1)
|
||||
DEFINE_SPECIAL(ACS_ExecuteAlways, 226, 2, 5)
|
||||
DEFINE_SPECIAL(ACS_ExecuteAlways, 226, 1, 5)
|
||||
DEFINE_SPECIAL(PointPush_SetForce, 227, -1, -1)
|
||||
DEFINE_SPECIAL(Plat_RaiseAndStayTx0, 228, 2, 2)
|
||||
DEFINE_SPECIAL(Thing_SetGoal, 229, 3, 4)
|
||||
|
|
|
@ -299,6 +299,7 @@ enum
|
|||
MF5_NEVERRESPAWN = 0x00040000, // never respawns, regardless of skill setting
|
||||
MF5_DONTRIP = 0x00080000, // Ripping projectiles explode when hittin this actor
|
||||
MF5_NOINFIGHTING = 0x00100000, // This actor doesn't switch target when it's hurt
|
||||
MF5_NOINTERACTION = 0x00200000, // Thing is completely excluded from any gameplay related checks
|
||||
|
||||
// --- mobj.renderflags ---
|
||||
|
||||
|
@ -702,6 +703,7 @@ public:
|
|||
//Added by MC:
|
||||
SDWORD id; // Player ID (for items, # in list.)
|
||||
|
||||
BYTE smokecounter;
|
||||
BYTE FloatBobPhase;
|
||||
BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc)
|
||||
DWORD Translation;
|
||||
|
@ -760,6 +762,7 @@ public:
|
|||
bool SetStateNF (FState *newstate);
|
||||
virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true);
|
||||
bool isFast();
|
||||
void SetIdle();
|
||||
|
||||
FState *FindState (FName label) const;
|
||||
FState *FindState (FName label, FName sublabel, bool exact = false) const;
|
||||
|
|
|
@ -115,8 +115,6 @@ inline fixed_t MTOF(fixed_t x)
|
|||
return MulScale24 (x, scale_mtof);
|
||||
}
|
||||
|
||||
//static int WeightingScale;
|
||||
|
||||
CVAR (Int, am_rotate, 0, CVAR_ARCHIVE);
|
||||
CVAR (Int, am_overlay, 0, CVAR_ARCHIVE);
|
||||
CVAR (Bool, am_showsecrets, true, CVAR_ARCHIVE);
|
||||
|
@ -125,7 +123,6 @@ CVAR (Bool, am_showitems, false, CVAR_ARCHIVE);
|
|||
CVAR (Bool, am_showtime, true, CVAR_ARCHIVE);
|
||||
CVAR (Bool, am_showtotaltime, false, CVAR_ARCHIVE);
|
||||
CVAR (Bool, am_usecustomcolors, true, CVAR_ARCHIVE);
|
||||
CVAR (Float, am_ovtrans, 1.f, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_backcolor, 0x6c5440, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_yourcolor, 0xfce8d8, CVAR_ARCHIVE);
|
||||
CVAR (Color, am_wallcolor, 0x2c1808, CVAR_ARCHIVE);
|
||||
|
@ -347,16 +344,6 @@ static fixed_t mapxstart=0; //x-value for the bitmap.
|
|||
static bool stopped = true;
|
||||
|
||||
|
||||
/*
|
||||
#define NUMALIASES 3
|
||||
#define WALLCOLORS -1
|
||||
#define FDWALLCOLORS -2
|
||||
#define CDWALLCOLORS -3
|
||||
|
||||
static BYTE antialias[NUMALIASES][NUMWEIGHTS];
|
||||
*/
|
||||
|
||||
|
||||
void AM_rotatePoint (fixed_t *x, fixed_t *y);
|
||||
void AM_rotate (fixed_t *x, fixed_t *y, angle_t an);
|
||||
void AM_doFollowPlayer ();
|
||||
|
@ -733,57 +720,6 @@ static void AM_initColors (bool overlayed)
|
|||
NotSeenColor = DoomColors[10];
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Due to a bug (marked below) precalculated antialiasing was never working properly.
|
||||
// Also, tests show it provides no measurable performance improvement.
|
||||
// And since it only complicates matters it's disabled for now.
|
||||
|
||||
// initialize the anti-aliased lines
|
||||
static struct
|
||||
{
|
||||
int *color;
|
||||
int prevcolor;
|
||||
int falseColor;
|
||||
} aliasedLines[3] = {
|
||||
{ &WallColor, -1, WALLCOLORS },
|
||||
{ &FDWallColor, -1, FDWALLCOLORS },
|
||||
{ &CDWallColor, -1, CDWALLCOLORS }
|
||||
};
|
||||
float backRed, backGreen, backBlue;
|
||||
|
||||
GetComponents (Background, palette, backRed, backGreen, backBlue);
|
||||
|
||||
for (int alias = 0; alias < NUMALIASES; alias++)
|
||||
{
|
||||
if (aliasedLines[alias].prevcolor != *(aliasedLines[alias].color) ||
|
||||
lastpal != palette || lastback != Background)
|
||||
{
|
||||
float foreRed, foreGreen, foreBlue;
|
||||
|
||||
aliasedLines[alias].prevcolor = *(aliasedLines[alias].color);
|
||||
GetComponents (*(aliasedLines[alias].color), palette, foreRed, foreGreen, foreBlue);
|
||||
|
||||
for (int i = 0; i < NUMWEIGHTS; i++)
|
||||
{
|
||||
float step = (float)i;
|
||||
float fore = (NUMWEIGHTS-1 - step) / (NUMWEIGHTS-1);
|
||||
float back = step / (NUMWEIGHTS-1);
|
||||
int red = (int)(backRed * back + foreRed * fore);
|
||||
int green = (int)(backGreen * back + foreGreen * fore);
|
||||
int blue = (int)(backGreen * back + foreBlue * fore);
|
||||
// [RH] What was I thinking here?
|
||||
// if (palette)
|
||||
antialias[alias][i] = ColorMatcher.Pick (red, green, blue);
|
||||
// else
|
||||
// antialias[alias][i] = MAKERGB(red, green, blue);
|
||||
}
|
||||
}
|
||||
// This line was inside the 'if' block rendering the whole
|
||||
// precalculation inoperable.
|
||||
*(aliasedLines[alias].color) = aliasedLines[alias].falseColor;
|
||||
}
|
||||
lastback = Background;
|
||||
#endif
|
||||
lastpal = palette;
|
||||
}
|
||||
|
||||
|
@ -1357,6 +1293,22 @@ void AM_drawGrid (const AMColor &color)
|
|||
}
|
||||
}
|
||||
|
||||
static bool AM_CheckSecret(line_t *line)
|
||||
{
|
||||
if (line->frontsector != NULL)
|
||||
{
|
||||
if (line->frontsector->oldspecial &&
|
||||
(am_map_secrets==2 || (am_map_secrets==1 && !(line->frontsector->special&SECRET_MASK))))
|
||||
return true;
|
||||
}
|
||||
if (line->backsector != NULL)
|
||||
{
|
||||
if (line->backsector->oldspecial &&
|
||||
(am_map_secrets==2 || (am_map_secrets==1 && !(line->backsector->special&SECRET_MASK))))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Determines visible lines, draws them.
|
||||
// This is LineDef based, not LineSeg based.
|
||||
|
@ -1384,19 +1336,15 @@ void AM_drawWalls (bool allmap)
|
|||
if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0)
|
||||
continue;
|
||||
|
||||
if (!lines[i].backsector)
|
||||
{
|
||||
if (lines[i].frontsector->oldspecial &&
|
||||
(am_map_secrets==2 || (am_map_secrets==1 && !(lines[i].frontsector->special&SECRET_MASK))))
|
||||
if (AM_CheckSecret(&lines[i]))
|
||||
{
|
||||
// map secret sectors like Boom
|
||||
AM_drawMline(&l, SecretSectorColor);
|
||||
}
|
||||
else
|
||||
else if (!lines[i].backsector)
|
||||
{
|
||||
AM_drawMline(&l, WallColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((lines[i].special == Teleport ||
|
||||
|
@ -1424,6 +1372,7 @@ void AM_drawWalls (bool allmap)
|
|||
}
|
||||
else if (lines[i].special == Door_LockedRaise ||
|
||||
lines[i].special == ACS_LockedExecute ||
|
||||
lines[i].special == ACS_LockedExecuteDoor ||
|
||||
(lines[i].special == Generic_Door && lines[i].args[4]!=0))
|
||||
{
|
||||
if (am_usecustomcolors)
|
||||
|
@ -1805,7 +1754,6 @@ void AM_Drawer ()
|
|||
f_w = screen->GetWidth ();
|
||||
f_h = ST_Y;
|
||||
f_p = screen->GetPitch ();
|
||||
//WeightingScale = 0;
|
||||
|
||||
AM_clearFB(Background);
|
||||
}
|
||||
|
@ -1816,13 +1764,6 @@ void AM_Drawer ()
|
|||
f_w = realviewwidth;
|
||||
f_h = realviewheight;
|
||||
f_p = screen->GetPitch ();
|
||||
/*
|
||||
WeightingScale = (int)(am_ovtrans * 256.f);
|
||||
if (WeightingScale < 0 || WeightingScale >= 256)
|
||||
{
|
||||
WeightingScale = 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
AM_activateNewScale();
|
||||
|
||||
|
|
|
@ -266,12 +266,10 @@ CCMD (idclev)
|
|||
// Catch invalid maps.
|
||||
mapname = CalcMapName (epsd, map);
|
||||
|
||||
MapData * mapd = P_OpenMapData(mapname);
|
||||
if (mapd == NULL)
|
||||
if (!P_CheckMapData(mapname))
|
||||
return;
|
||||
|
||||
// So be it.
|
||||
delete mapd;
|
||||
Printf ("%s\n", GStrings("STSTR_CLEV"));
|
||||
G_DeferedInitNew (mapname);
|
||||
players[0].health = 0; // Force reset
|
||||
|
@ -293,11 +291,9 @@ CCMD (hxvisit)
|
|||
{
|
||||
// Just because it's in MAPINFO doesn't mean it's in the wad.
|
||||
|
||||
MapData * map = P_OpenMapData(mapname);
|
||||
if (map != NULL)
|
||||
if (P_CheckMapData(mapname))
|
||||
{
|
||||
// So be it.
|
||||
delete map;
|
||||
Printf ("%s\n", GStrings("STSTR_CLEV"));
|
||||
G_DeferedInitNew (mapname);
|
||||
return;
|
||||
|
@ -323,14 +319,12 @@ CCMD (changemap)
|
|||
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
MapData * map = P_OpenMapData(argv[1]);
|
||||
if (map == NULL)
|
||||
if (!P_CheckMapData(argv[1]))
|
||||
{
|
||||
Printf ("No map %s\n", argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete map;
|
||||
if (argv.argc() > 2)
|
||||
{
|
||||
Net_WriteByte (DEM_CHANGEMAP2);
|
||||
|
|
|
@ -2184,8 +2184,15 @@ void DoDehPatch (const char *patchfile, bool autoloading)
|
|||
if (!PatchFile)
|
||||
{
|
||||
// Couldn't find it on disk, try reading it from a lump
|
||||
lump = Wads.CheckNumForFullName(patchfile, true);
|
||||
if (lump == -1)
|
||||
{
|
||||
// Compatibility fallback. It's just here because
|
||||
// some WAD may need it. Should be deleted it it can
|
||||
// be confirmed that nothing uses this case.
|
||||
FString filebase(ExtractFileBase (patchfile));
|
||||
lump = Wads.CheckNumForName (filebase);
|
||||
}
|
||||
if (lump >= 0)
|
||||
{
|
||||
filelen = Wads.LumpLength (lump);
|
||||
|
|
|
@ -1013,10 +1013,8 @@ void D_DoAdvanceDemo (void)
|
|||
// [RH] If you want something more dynamic for your title, create a map
|
||||
// and name it TITLEMAP. That map will be loaded and used as the title.
|
||||
|
||||
MapData * map = P_OpenMapData("TITLEMAP");
|
||||
if (map != NULL)
|
||||
if (P_CheckMapData("TITLEMAP"))
|
||||
{
|
||||
delete map;
|
||||
G_InitNew ("TITLEMAP", true);
|
||||
return;
|
||||
}
|
||||
|
@ -2281,14 +2279,12 @@ void D_DoomMain (void)
|
|||
p = Args->CheckParm ("+map");
|
||||
if (p && p < Args->NumArgs()-1)
|
||||
{
|
||||
MapData * map = P_OpenMapData(Args->GetArg (p+1));
|
||||
if (map == NULL)
|
||||
if (!P_CheckMapData(Args->GetArg (p+1)))
|
||||
{
|
||||
Printf ("Can't find map %s\n", Args->GetArg (p+1));
|
||||
}
|
||||
else
|
||||
{
|
||||
delete map;
|
||||
strncpy (startmap, Args->GetArg (p+1), 8);
|
||||
Args->GetArg (p)[0] = '-';
|
||||
autostart = true;
|
||||
|
@ -2355,10 +2351,6 @@ void D_DoomMain (void)
|
|||
StartScreen->AppendStatusLine(temp);
|
||||
}
|
||||
|
||||
// [RH] Now that all text strings are set up,
|
||||
// insert them into the level and cluster data.
|
||||
G_MakeEpisodes ();
|
||||
|
||||
// [RH] Parse through all loaded mapinfo lumps
|
||||
Printf ("G_ParseMapInfo: Load map definitions.\n");
|
||||
G_ParseMapInfo ();
|
||||
|
|
|
@ -51,6 +51,7 @@ enum
|
|||
|
||||
APMETA_DisplayName, // display name (used in menus etc.)
|
||||
APMETA_SoundClass, // sound class
|
||||
APMETA_Face, // doom status bar face (when used)
|
||||
APMETA_ColorRange, // skin color range
|
||||
APMETA_InvulMode,
|
||||
APMETA_HealingRadius,
|
||||
|
@ -252,6 +253,7 @@ public:
|
|||
int fixedcolormap; // can be set to REDCOLORMAP, etc.
|
||||
pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc)
|
||||
int morphTics; // player is a chicken/pig if > 0
|
||||
BYTE MorphedPlayerClass; // [MH] (for SBARINFO) class # for this player instance when morphed
|
||||
AWeapon *PremorphWeapon; // ready weapon before morphing
|
||||
int chickenPeck; // chicken peck countdown
|
||||
int jumpTics; // delay the next jump for a moment
|
||||
|
|
|
@ -346,7 +346,7 @@ void FDecalLib::ReadAllDecals ()
|
|||
|
||||
while ((lump = Wads.FindLump ("DECALDEF", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump, "DECALDEF");
|
||||
FScanner sc(lump);
|
||||
ReadDecals (sc);
|
||||
}
|
||||
// Supporting code to allow specifying decals directly in the DECORATE lump
|
||||
|
|
|
@ -149,9 +149,6 @@ extern int viewangleoffset;
|
|||
extern int consoleplayer;
|
||||
|
||||
|
||||
extern level_locals_t level;
|
||||
|
||||
|
||||
// --------------------------------------
|
||||
// DEMO playback/recording related stuff.
|
||||
// No demo, there is a human player in charge?
|
||||
|
|
|
@ -1314,7 +1314,7 @@ static void GetFinaleText (const char *msgLumpName)
|
|||
{
|
||||
int msgLump;
|
||||
|
||||
msgLump = Wads.CheckNumForName(msgLumpName);
|
||||
msgLump = Wads.CheckNumForFullName(msgLumpName, true);
|
||||
if (msgLump != -1)
|
||||
{
|
||||
char *textbuf;
|
||||
|
|
|
@ -9,7 +9,6 @@ class AActor;
|
|||
|
||||
void T_PreprocessScripts();
|
||||
void T_LoadScripts(MapData * map);
|
||||
void T_PrepareSpawnThing();
|
||||
void T_RegisterSpawnThing(AActor * );
|
||||
void T_AddSpawnedThing(AActor * );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -304,31 +304,15 @@ void T_LoadScripts(MapData *map)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Registers an entry in the SpawnedThings table
|
||||
// If no actor is spawned it will remain NULL, otherwise T_RegisterSpawnThing
|
||||
// will be called to set it
|
||||
// Adds an actor to the list of spawned things
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void T_PrepareSpawnThing()
|
||||
{
|
||||
if (DFraggleThinker::ActiveThinker)
|
||||
{
|
||||
DFraggleThinker::ActiveThinker->SpawnedThings.Push(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Sets the last entry in the table to the passed actor
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void T_RegisterSpawnThing(AActor * ac)
|
||||
void T_AddSpawnedThing(AActor * ac)
|
||||
{
|
||||
if (DFraggleThinker::ActiveThinker)
|
||||
{
|
||||
TArray<TObjPtr<AActor> > &SpawnedThings = DFraggleThinker::ActiveThinker->SpawnedThings;
|
||||
SpawnedThings[SpawnedThings.Size()-1] = ac;
|
||||
SpawnedThings.Push(GC::ReadBarrier(ac));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -617,7 +617,7 @@ void T_PreprocessScripts()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool T_RunScript(int snum, AActor * t_trigger)
|
||||
static bool RunScript(int snum, AActor * t_trigger)
|
||||
{
|
||||
DFraggleThinker *th = DFraggleThinker::ActiveThinker;
|
||||
if (th)
|
||||
|
@ -651,7 +651,7 @@ static int LS_FS_Execute (line_t *ln, AActor *it, bool backSide,
|
|||
{
|
||||
if (arg1 && ln && backSide) return false;
|
||||
if (arg2!=0 && !P_CheckKeys(it, arg2, !!arg3)) return false;
|
||||
return T_RunScript(arg0,it);
|
||||
return RunScript(arg0,it);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -713,6 +713,6 @@ CCMD(fpuke)
|
|||
}
|
||||
else
|
||||
{
|
||||
T_RunScript(atoi(argv[1]), players[consoleplayer].mo);
|
||||
RunScript(atoi(argv[1]), players[consoleplayer].mo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ void A_Punch (AActor *actor)
|
|||
|
||||
angle += pr_punch.Random2() << 18;
|
||||
pitch = P_AimLineAttack (actor, angle, MELEERANGE);
|
||||
P_LineAttack (actor, angle, MELEERANGE, pitch, damage, NAME_None, NAME_BulletPuff);
|
||||
P_LineAttack (actor, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true);
|
||||
|
||||
// turn to face target
|
||||
if (linetarget)
|
||||
|
|
|
@ -456,7 +456,7 @@ void A_M_Punch (AActor *self)
|
|||
A_FaceTarget (self);
|
||||
angle = self->angle + (pr_m_punch.Random2() << 18);
|
||||
pitch = P_AimLineAttack (self, angle, MELEERANGE);
|
||||
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff);
|
||||
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true);
|
||||
|
||||
// turn to face target
|
||||
if (linetarget)
|
||||
|
@ -486,7 +486,7 @@ void A_M_BerserkPunch (AActor *self)
|
|||
A_FaceTarget (self);
|
||||
angle = self->angle + (pr_m_punch.Random2() << 18);
|
||||
pitch = P_AimLineAttack (self, angle, MELEERANGE);
|
||||
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff);
|
||||
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true);
|
||||
|
||||
// turn to face target
|
||||
if (linetarget)
|
||||
|
|
|
@ -2291,11 +2291,11 @@ void G_BeginRecording (const char *startmap)
|
|||
// G_PlayDemo
|
||||
//
|
||||
|
||||
char defdemoname[128];
|
||||
FString defdemoname;
|
||||
|
||||
void G_DeferedPlayDemo (char *name)
|
||||
{
|
||||
strncpy (defdemoname, name, 127);
|
||||
defdemoname = name;
|
||||
gameaction = ga_playdemo;
|
||||
}
|
||||
|
||||
|
@ -2457,7 +2457,7 @@ void G_DoPlayDemo (void)
|
|||
gameaction = ga_nothing;
|
||||
|
||||
// [RH] Allow for demos not loaded as lumps
|
||||
demolump = Wads.CheckNumForName (defdemoname);
|
||||
demolump = Wads.CheckNumForFullName (defdemoname, true);
|
||||
if (demolump >= 0)
|
||||
{
|
||||
int demolen = Wads.LumpLength (demolump);
|
||||
|
@ -2472,7 +2472,7 @@ void G_DoPlayDemo (void)
|
|||
}
|
||||
demo_p = demobuffer;
|
||||
|
||||
Printf ("Playing demo %s\n", defdemoname);
|
||||
Printf ("Playing demo %s\n", defdemoname.GetChars());
|
||||
|
||||
C_BackupCVars (); // [RH] Save cvars that might be affected by demo
|
||||
|
||||
|
@ -2520,7 +2520,7 @@ void G_TimeDemo (char* name)
|
|||
timingdemo = true;
|
||||
singletics = true;
|
||||
|
||||
strncpy (defdemoname, name, 128);
|
||||
defdemoname = name;
|
||||
gameaction = ga_playdemo;
|
||||
}
|
||||
|
||||
|
|
|
@ -412,7 +412,7 @@ void A_BeakAttackPL1 (AActor *actor)
|
|||
damage = 1 + (pr_beakatkpl1()&3);
|
||||
angle = player->mo->angle;
|
||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(ABeakPuff));
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(ABeakPuff), true);
|
||||
if (linetarget)
|
||||
{
|
||||
player->mo->angle = R_PointToAngle2 (player->mo->x,
|
||||
|
@ -444,7 +444,7 @@ void A_BeakAttackPL2 (AActor *actor)
|
|||
damage = pr_beakatkpl2.HitDice (4);
|
||||
angle = player->mo->angle;
|
||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(ABeakPuff));
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(ABeakPuff), true);
|
||||
if (linetarget)
|
||||
{
|
||||
player->mo->angle = R_PointToAngle2 (player->mo->x,
|
||||
|
|
|
@ -217,7 +217,7 @@ void A_StaffAttackPL1 (AActor *actor)
|
|||
angle = player->mo->angle;
|
||||
angle += pr_sap.Random2() << 18;
|
||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AStaffPuff));
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AStaffPuff), true);
|
||||
if (linetarget)
|
||||
{
|
||||
//S_StartSound(player->mo, sfx_stfhit);
|
||||
|
@ -256,7 +256,7 @@ void A_StaffAttackPL2 (AActor *actor)
|
|||
angle = player->mo->angle;
|
||||
angle += pr_sap2.Random2() << 18;
|
||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AStaffPuff2));
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AStaffPuff2), true);
|
||||
if (linetarget)
|
||||
{
|
||||
//S_StartSound(player->mo, sfx_stfpow);
|
||||
|
|
|
@ -94,7 +94,7 @@ void A_CMaceAttack (AActor *actor)
|
|||
slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE);
|
||||
if (linetarget)
|
||||
{
|
||||
P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AHammerPuff));
|
||||
P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AHammerPuff), true);
|
||||
AdjustPlayerAngle (player->mo);
|
||||
// player->mo->angle = R_PointToAngle2(player->mo->x,
|
||||
// player->mo->y, linetarget->x, linetarget->y);
|
||||
|
@ -104,7 +104,7 @@ void A_CMaceAttack (AActor *actor)
|
|||
slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE);
|
||||
if (linetarget)
|
||||
{
|
||||
P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AHammerPuff));
|
||||
P_LineAttack (player->mo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AHammerPuff), true);
|
||||
AdjustPlayerAngle (player->mo);
|
||||
// player->mo->angle = R_PointToAngle2(player->mo->x,
|
||||
// player->mo->y, linetarget->x, linetarget->y);
|
||||
|
|
|
@ -352,7 +352,7 @@ void A_FAxeAttack (AActor *actor)
|
|||
slope = P_AimLineAttack (pmo, angle, AXERANGE);
|
||||
if (linetarget)
|
||||
{
|
||||
P_LineAttack (pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype);
|
||||
P_LineAttack (pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true);
|
||||
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||||
{
|
||||
P_ThrustMobj (linetarget, angle, power);
|
||||
|
@ -365,7 +365,7 @@ void A_FAxeAttack (AActor *actor)
|
|||
slope = P_AimLineAttack (pmo, angle, AXERANGE);
|
||||
if (linetarget)
|
||||
{
|
||||
P_LineAttack (pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype);
|
||||
P_LineAttack (pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true);
|
||||
if (linetarget->flags3&MF3_ISMONSTER)
|
||||
{
|
||||
P_ThrustMobj (linetarget, angle, power);
|
||||
|
@ -380,7 +380,7 @@ void A_FAxeAttack (AActor *actor)
|
|||
|
||||
angle = pmo->angle;
|
||||
slope = P_AimLineAttack (pmo, angle, MELEERANGE);
|
||||
P_LineAttack (pmo, angle, MELEERANGE, slope, damage, NAME_Melee, pufftype);
|
||||
P_LineAttack (pmo, angle, MELEERANGE, slope, damage, NAME_Melee, pufftype, true);
|
||||
|
||||
axedone:
|
||||
if (useMana == 2)
|
||||
|
|
|
@ -194,7 +194,7 @@ void A_FHammerAttack (AActor *actor)
|
|||
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE);
|
||||
if (linetarget)
|
||||
{
|
||||
P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AHammerPuff));
|
||||
P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AHammerPuff), true);
|
||||
AdjustPlayerAngle(pmo);
|
||||
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||||
{
|
||||
|
@ -207,7 +207,7 @@ void A_FHammerAttack (AActor *actor)
|
|||
slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE);
|
||||
if(linetarget)
|
||||
{
|
||||
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AHammerPuff));
|
||||
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AHammerPuff), true);
|
||||
AdjustPlayerAngle(pmo);
|
||||
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||||
{
|
||||
|
@ -220,7 +220,7 @@ void A_FHammerAttack (AActor *actor)
|
|||
// didn't find any targets in meleerange, so set to throw out a hammer
|
||||
angle = pmo->angle;
|
||||
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE);
|
||||
if (P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AHammerPuff)) != NULL)
|
||||
if (P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(AHammerPuff), true) != NULL)
|
||||
{
|
||||
pmo->special1 = false;
|
||||
}
|
||||
|
|
|
@ -258,7 +258,7 @@ void A_FPunchAttack (AActor *actor)
|
|||
power = 6*FRACUNIT;
|
||||
pufftype = RUNTIME_CLASS(AHammerPuff);
|
||||
}
|
||||
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype);
|
||||
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true);
|
||||
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||||
{
|
||||
P_ThrustMobj (linetarget, angle, power);
|
||||
|
@ -277,7 +277,7 @@ void A_FPunchAttack (AActor *actor)
|
|||
power = 6*FRACUNIT;
|
||||
pufftype = RUNTIME_CLASS(AHammerPuff);
|
||||
}
|
||||
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype);
|
||||
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true);
|
||||
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||||
{
|
||||
P_ThrustMobj (linetarget, angle, power);
|
||||
|
@ -291,7 +291,7 @@ void A_FPunchAttack (AActor *actor)
|
|||
|
||||
angle = pmo->angle;
|
||||
slope = P_AimLineAttack (pmo, angle, MELEERANGE);
|
||||
P_LineAttack (pmo, angle, MELEERANGE, slope, damage, NAME_Melee, pufftype);
|
||||
P_LineAttack (pmo, angle, MELEERANGE, slope, damage, NAME_Melee, pufftype, true);
|
||||
|
||||
punchdone:
|
||||
if (pmo->special1 == 3)
|
||||
|
|
|
@ -269,7 +269,7 @@ void A_SnoutAttack (AActor *actor)
|
|||
damage = 3+(pr_snoutattack()&3);
|
||||
angle = player->mo->angle;
|
||||
slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
|
||||
puff = P_LineAttack(player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(ASnoutPuff));
|
||||
puff = P_LineAttack(player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(ASnoutPuff), true);
|
||||
S_Sound(player->mo, CHAN_VOICE, "PigActive", 1, ATTN_NORM);
|
||||
if(linetarget)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "gi.h"
|
||||
#include "files.h"
|
||||
#include "m_png.h"
|
||||
#include "gstrings.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
@ -101,8 +102,15 @@ void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs)
|
|||
}
|
||||
}
|
||||
if (cluster->clustername)
|
||||
{
|
||||
if (cluster->flags & CLUSTER_LOOKUPNAME)
|
||||
{
|
||||
strncpy(level.level_name, GStrings(cluster->clustername), 64);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(level.level_name, cluster->clustername, 64);
|
||||
}
|
||||
level.level_name[63]=0;
|
||||
}
|
||||
}
|
||||
|
|
358
src/g_level.cpp
358
src/g_level.cpp
|
@ -137,7 +137,7 @@ extern const AInventory *SendItemUse, *SendItemDrop;
|
|||
|
||||
void *statcopy; // for statistics driver
|
||||
|
||||
level_locals_t level; // info about current level
|
||||
FLevelLocals level; // info about current level
|
||||
|
||||
static TArray<cluster_info_t> wadclusterinfos;
|
||||
TArray<level_info_t> wadlevelinfos;
|
||||
|
@ -180,6 +180,7 @@ static const char *MapInfoTopLevel[] =
|
|||
"clearepisodes",
|
||||
"skill",
|
||||
"clearskills",
|
||||
"adddefaultmap",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -192,6 +193,7 @@ enum
|
|||
MITL_CLEAREPISODES,
|
||||
MITL_SKILL,
|
||||
MITL_CLEARSKILLS,
|
||||
MITL_ADDDEFAULTMAP,
|
||||
};
|
||||
|
||||
static const char *MapInfoMapLevel[] =
|
||||
|
@ -337,7 +339,6 @@ enum EMIType
|
|||
MITYPE_REDIRECT,
|
||||
MITYPE_SPECIALACTION,
|
||||
MITYPE_COMPATFLAG,
|
||||
MITYPE_F1, // [RC] F1 help
|
||||
};
|
||||
|
||||
struct MapInfoHandler
|
||||
|
@ -414,18 +415,18 @@ MapHandlers[] =
|
|||
{ MITYPE_CLRFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO },
|
||||
{ MITYPE_SETFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO },
|
||||
{ MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL},
|
||||
{ MITYPE_LUMPNAME, lioffset(exitpic), 0 },
|
||||
{ MITYPE_LUMPNAME, lioffset(exitpic), 0 },
|
||||
{ MITYPE_LUMPNAME, lioffset(enterpic), 0 },
|
||||
{ MITYPE_STRING, lioffset(exitpic), 0 },
|
||||
{ MITYPE_STRING, lioffset(exitpic), 0 },
|
||||
{ MITYPE_STRING, lioffset(enterpic), 0 },
|
||||
{ MITYPE_MUSIC, lioffset(intermusic), lioffset(intermusicorder) },
|
||||
{ MITYPE_INT, lioffset(airsupply), 0 },
|
||||
{ MITYPE_SPECIALACTION, lioffset(specialactions), 0 },
|
||||
{ MITYPE_SETFLAG, LEVEL_KEEPFULLINVENTORY, 0 },
|
||||
{ MITYPE_SETFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
|
||||
{ MITYPE_CLRFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
|
||||
{ MITYPE_LUMPNAME, lioffset(sndseq), 0 },
|
||||
{ MITYPE_LUMPNAME, lioffset(soundinfo), 0 },
|
||||
{ MITYPE_LUMPNAME, lioffset(soundinfo), 0 },
|
||||
{ MITYPE_STRING, lioffset(sndseq), 0 },
|
||||
{ MITYPE_STRING, lioffset(soundinfo), 0 },
|
||||
{ MITYPE_STRING, lioffset(soundinfo), 0 },
|
||||
{ MITYPE_SETFLAG, LEVEL_CLIPMIDTEX, 0 },
|
||||
{ MITYPE_SETFLAG, LEVEL_WRAPMIDTEX, 0 },
|
||||
{ MITYPE_CLRFLAG, LEVEL_CROUCH_NO, 0 },
|
||||
|
@ -446,7 +447,7 @@ MapHandlers[] =
|
|||
{ MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL},
|
||||
{ MITYPE_COMPATFLAG, COMPATF_INVISIBILITY},
|
||||
{ MITYPE_LUMPNAME, lioffset(bordertexture), 0 },
|
||||
{ MITYPE_F1, lioffset(f1), 0, },
|
||||
{ MITYPE_LUMPNAME, lioffset(f1), 0, },
|
||||
{ MITYPE_SCFLAGS, LEVEL_NOINFIGHTING, ~LEVEL_TOTALINFIGHTING },
|
||||
{ MITYPE_SCFLAGS, 0, ~(LEVEL_NOINFIGHTING|LEVEL_TOTALINFIGHTING)},
|
||||
{ MITYPE_SCFLAGS, LEVEL_TOTALINFIGHTING, ~LEVEL_NOINFIGHTING },
|
||||
|
@ -493,7 +494,7 @@ MapInfoHandler ClusterHandlers[] =
|
|||
{ MITYPE_HEX, cioffset(cdid), 0 },
|
||||
{ MITYPE_SETFLAG, CLUSTER_ENTERTEXTINLUMP, 0 },
|
||||
{ MITYPE_SETFLAG, CLUSTER_EXITTEXTINLUMP, 0 },
|
||||
{ MITYPE_STRING, cioffset(clustername), 0 },
|
||||
{ MITYPE_STRING, cioffset(clustername), CLUSTER_LOOKUPNAME },
|
||||
};
|
||||
|
||||
static void ParseMapInfoLower (FScanner &sc,
|
||||
|
@ -537,10 +538,6 @@ static void SetLevelDefaults (level_info_t *levelinfo)
|
|||
// For maps without a BEHAVIOR, this will be cleared.
|
||||
levelinfo->flags |= LEVEL_LAXMONSTERACTIVATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
levelinfo->flags |= LEVEL_MONSTERFALLINGDAMAGE;
|
||||
}
|
||||
levelinfo->airsupply = 10;
|
||||
|
||||
// new
|
||||
|
@ -627,6 +624,48 @@ static FSpecialAction *CopySpecialActions(FSpecialAction *spec)
|
|||
return spec;
|
||||
}
|
||||
|
||||
static void CopyString (char *& string)
|
||||
{
|
||||
if (string != NULL)
|
||||
string = copystring(string);
|
||||
}
|
||||
|
||||
static void SafeDelete(char *&string)
|
||||
{
|
||||
if (string != NULL)
|
||||
{
|
||||
delete[] string;
|
||||
string = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ClearLevelInfoStrings(level_info_t *linfo)
|
||||
{
|
||||
SafeDelete(linfo->music);
|
||||
SafeDelete(linfo->intermusic);
|
||||
SafeDelete(linfo->level_name);
|
||||
SafeDelete(linfo->translator);
|
||||
SafeDelete(linfo->enterpic);
|
||||
SafeDelete(linfo->exitpic);
|
||||
SafeDelete(linfo->soundinfo);
|
||||
SafeDelete(linfo->sndseq);
|
||||
for (FSpecialAction *spac = linfo->specialactions; spac != NULL; )
|
||||
{
|
||||
FSpecialAction *next = spac->Next;
|
||||
delete spac;
|
||||
spac = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void ClearClusterInfoStrings(cluster_info_t *cinfo)
|
||||
{
|
||||
SafeDelete(cinfo->exittext);
|
||||
SafeDelete(cinfo->entertext);
|
||||
SafeDelete(cinfo->messagemusic);
|
||||
SafeDelete(cinfo->clustername);
|
||||
}
|
||||
|
||||
|
||||
static void G_DoParseMapInfo (int lump)
|
||||
{
|
||||
level_info_t defaultinfo;
|
||||
|
@ -636,7 +675,7 @@ static void G_DoParseMapInfo (int lump)
|
|||
int clusterindex;
|
||||
QWORD levelflags;
|
||||
|
||||
FScanner sc(lump, Wads.GetLumpFullName(lump));
|
||||
FScanner sc(lump);
|
||||
|
||||
SetLevelDefaults (&defaultinfo);
|
||||
HexenHack = false;
|
||||
|
@ -651,6 +690,11 @@ static void G_DoParseMapInfo (int lump)
|
|||
ParseMapInfoLower (sc, MapHandlers, MapInfoMapLevel, &defaultinfo, NULL, defaultinfo.flags);
|
||||
break;
|
||||
|
||||
case MITL_ADDDEFAULTMAP:
|
||||
// Same as above but adds to the existing definitions instead of replacing them completely
|
||||
ParseMapInfoLower (sc, MapHandlers, MapInfoMapLevel, &defaultinfo, NULL, defaultinfo.flags);
|
||||
break;
|
||||
|
||||
case MITL_MAP: // map <MAPNAME> <Nice Name>
|
||||
levelflags = defaultinfo.flags;
|
||||
sc.MustGetString ();
|
||||
|
@ -668,7 +712,8 @@ static void G_DoParseMapInfo (int lump)
|
|||
| LEVEL_FALLDMG_HX
|
||||
| LEVEL_ACTOWNSPECIAL
|
||||
| LEVEL_MISSILESACTIVATEIMPACT
|
||||
| LEVEL_INFINITE_FLIGHT;
|
||||
| LEVEL_INFINITE_FLIGHT
|
||||
| LEVEL_MONSTERFALLINGDAMAGE;
|
||||
}
|
||||
levelindex = FindWadLevelInfo (sc.String);
|
||||
if (levelindex == -1)
|
||||
|
@ -681,18 +726,13 @@ static void G_DoParseMapInfo (int lump)
|
|||
}
|
||||
levelinfo = &wadlevelinfos[levelindex];
|
||||
memcpy (levelinfo, &defaultinfo, sizeof(*levelinfo));
|
||||
if (levelinfo->music != NULL)
|
||||
{
|
||||
levelinfo->music = copystring (levelinfo->music);
|
||||
}
|
||||
if (levelinfo->intermusic != NULL)
|
||||
{
|
||||
levelinfo->intermusic = copystring (levelinfo->intermusic);
|
||||
}
|
||||
if (levelinfo->translator != NULL)
|
||||
{
|
||||
levelinfo->translator = copystring (levelinfo->translator);
|
||||
}
|
||||
CopyString(levelinfo->music);
|
||||
CopyString(levelinfo->intermusic);
|
||||
CopyString(levelinfo->translator);
|
||||
CopyString(levelinfo->enterpic);
|
||||
CopyString(levelinfo->exitpic);
|
||||
CopyString(levelinfo->soundinfo);
|
||||
CopyString(levelinfo->sndseq);
|
||||
levelinfo->specialactions = CopySpecialActions(levelinfo->specialactions);
|
||||
if (HexenHack)
|
||||
{
|
||||
|
@ -700,14 +740,19 @@ static void G_DoParseMapInfo (int lump)
|
|||
}
|
||||
uppercopy (levelinfo->mapname, sc.String);
|
||||
sc.MustGetString ();
|
||||
if (sc.Compare ("lookup"))
|
||||
if (sc.String[0] == '$')
|
||||
{
|
||||
sc.MustGetString ();
|
||||
ReplaceString (&levelinfo->level_name, sc.String);
|
||||
// For consistency with other definitions allow $Stringtablename here, too.
|
||||
levelflags |= LEVEL_LOOKUPLEVELNAME;
|
||||
ReplaceString (&levelinfo->level_name, sc.String+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sc.Compare ("lookup"))
|
||||
{
|
||||
sc.MustGetString ();
|
||||
levelflags |= LEVEL_LOOKUPLEVELNAME;
|
||||
}
|
||||
ReplaceString (&levelinfo->level_name, sc.String);
|
||||
}
|
||||
// Set up levelnum now so that you can use Teleport_NewMap specials
|
||||
|
@ -734,10 +779,6 @@ static void G_DoParseMapInfo (int lump)
|
|||
{
|
||||
strcpy (levelinfo->skypic2, levelinfo->skypic1);
|
||||
}
|
||||
if (levelinfo->f1 != NULL)
|
||||
{
|
||||
levelinfo->f1 = copystring (levelinfo->f1);
|
||||
}
|
||||
SetLevelNum (levelinfo, levelinfo->levelnum); // Wipe out matching levelnums from other maps.
|
||||
if (levelinfo->pname[0] != 0)
|
||||
{
|
||||
|
@ -759,22 +800,7 @@ static void G_DoParseMapInfo (int lump)
|
|||
else
|
||||
{
|
||||
clusterinfo = &wadclusterinfos[clusterindex];
|
||||
if (clusterinfo->entertext != NULL)
|
||||
{
|
||||
delete[] clusterinfo->entertext;
|
||||
}
|
||||
if (clusterinfo->exittext != NULL)
|
||||
{
|
||||
delete[] clusterinfo->exittext;
|
||||
}
|
||||
if (clusterinfo->messagemusic != NULL)
|
||||
{
|
||||
delete[] clusterinfo->messagemusic;
|
||||
}
|
||||
if (clusterinfo->clustername != NULL)
|
||||
{
|
||||
delete[] clusterinfo->clustername;
|
||||
}
|
||||
ClearClusterInfoStrings(clusterinfo);
|
||||
}
|
||||
memset (clusterinfo, 0, sizeof(cluster_info_t));
|
||||
clusterinfo->cluster = sc.Number;
|
||||
|
@ -802,60 +828,6 @@ static void G_DoParseMapInfo (int lump)
|
|||
ClearLevelInfoStrings(&defaultinfo);
|
||||
}
|
||||
|
||||
static void ClearLevelInfoStrings(level_info_t *linfo)
|
||||
{
|
||||
if (linfo->music != NULL)
|
||||
{
|
||||
delete[] linfo->music;
|
||||
linfo->music = NULL;
|
||||
}
|
||||
if (linfo->intermusic != NULL)
|
||||
{
|
||||
delete[] linfo->intermusic;
|
||||
linfo->intermusic = NULL;
|
||||
}
|
||||
if (linfo->level_name != NULL)
|
||||
{
|
||||
delete[] linfo->level_name;
|
||||
linfo->level_name = NULL;
|
||||
}
|
||||
if (linfo->translator != NULL)
|
||||
{
|
||||
delete[] linfo->translator;
|
||||
linfo->translator = NULL;
|
||||
}
|
||||
for (FSpecialAction *spac = linfo->specialactions; spac != NULL; )
|
||||
{
|
||||
FSpecialAction *next = spac->Next;
|
||||
delete spac;
|
||||
spac = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void ClearClusterInfoStrings(cluster_info_t *cinfo)
|
||||
{
|
||||
if (cinfo->exittext != NULL)
|
||||
{
|
||||
delete[] cinfo->exittext;
|
||||
cinfo->exittext = NULL;
|
||||
}
|
||||
if (cinfo->entertext != NULL)
|
||||
{
|
||||
delete[] cinfo->entertext;
|
||||
cinfo->entertext = NULL;
|
||||
}
|
||||
if (cinfo->messagemusic != NULL)
|
||||
{
|
||||
delete[] cinfo->messagemusic;
|
||||
cinfo->messagemusic = NULL;
|
||||
}
|
||||
if (cinfo->clustername != NULL)
|
||||
{
|
||||
delete[] cinfo->clustername;
|
||||
cinfo->clustername = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void ClearEpisodes()
|
||||
{
|
||||
for (int i = 0; i < EpiDef.numitems; ++i)
|
||||
|
@ -920,13 +892,6 @@ static void ParseMapInfoLower (FScanner &sc,
|
|||
case MITYPE_REDIRECT:
|
||||
sc.MustGetString ();
|
||||
levelinfo->RedirectType = sc.String;
|
||||
/*
|
||||
if (levelinfo->RedirectType == NULL ||
|
||||
!(levelinfo->RedirectType->IsDescendantOf (RUNTIME_CLASS(AInventory))))
|
||||
{
|
||||
SC_ScriptError ("%s is not an inventory item", sc.String);
|
||||
}
|
||||
*/
|
||||
// Intentional fall-through
|
||||
|
||||
case MITYPE_MAPNAME: {
|
||||
|
@ -1064,7 +1029,7 @@ static void ParseMapInfoLower (FScanner &sc,
|
|||
clusterinfo = &wadclusterinfos[clusterindex];
|
||||
memset (clusterinfo, 0, sizeof(cluster_info_t));
|
||||
clusterinfo->cluster = sc.Number;
|
||||
if (gameinfo.gametype == GAME_Hexen)
|
||||
if (HexenHack)
|
||||
{
|
||||
clusterinfo->flags |= CLUSTER_HUB;
|
||||
}
|
||||
|
@ -1073,23 +1038,20 @@ static void ParseMapInfoLower (FScanner &sc,
|
|||
|
||||
case MITYPE_STRING:
|
||||
sc.MustGetString ();
|
||||
if (sc.String[0] == '$')
|
||||
{
|
||||
// For consistency with other definitions allow $Stringtablename here, too.
|
||||
flags |= handler->data2;
|
||||
ReplaceString ((char **)(info + handler->data1), sc.String+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sc.Compare ("lookup"))
|
||||
{
|
||||
flags |= handler->data2;
|
||||
sc.MustGetString ();
|
||||
}
|
||||
ReplaceString ((char **)(info + handler->data1), sc.String);
|
||||
break;
|
||||
|
||||
case MITYPE_F1:
|
||||
sc.MustGetString ();
|
||||
{
|
||||
char *colon = strchr (sc.String, ':');
|
||||
if (colon)
|
||||
{
|
||||
*colon = 0;
|
||||
}
|
||||
ReplaceString ((char **)(info + handler->data1), sc.String);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1194,6 +1156,7 @@ static void ParseEpisodeInfo (FScanner &sc)
|
|||
bool remove = false;
|
||||
char key = 0;
|
||||
bool noskill = false;
|
||||
bool optional = false;
|
||||
|
||||
// Get map name
|
||||
sc.MustGetString ();
|
||||
|
@ -1212,7 +1175,12 @@ static void ParseEpisodeInfo (FScanner &sc)
|
|||
}
|
||||
do
|
||||
{
|
||||
if (sc.Compare ("name"))
|
||||
if (sc.Compare ("optional"))
|
||||
{
|
||||
// For M4 in Doom and M4 and M5 in Heretic
|
||||
optional = true;
|
||||
}
|
||||
else if (sc.Compare ("name"))
|
||||
{
|
||||
sc.MustGetString ();
|
||||
ReplaceString (&pic, sc.String);
|
||||
|
@ -1245,6 +1213,17 @@ static void ParseEpisodeInfo (FScanner &sc)
|
|||
}
|
||||
while (sc.GetString ());
|
||||
|
||||
if (optional && !remove)
|
||||
{
|
||||
if (!P_CheckMapData(map))
|
||||
{
|
||||
// If the episode is optional and the map does not exist
|
||||
// just ignore this episode definition.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < EpiDef.numitems; ++i)
|
||||
{
|
||||
if (strncmp (EpisodeMaps[i], map, 8) == 0)
|
||||
|
@ -1412,8 +1391,8 @@ void P_RemoveDefereds (void)
|
|||
|
||||
bool CheckWarpTransMap (char mapname[9], bool substitute)
|
||||
{
|
||||
if (mapname[0] == '&' && mapname[1] == 'w' &&
|
||||
mapname[2] == 't' && mapname[3] == '@')
|
||||
if (mapname[0] == '&' && (mapname[1]&223) == 'W' &&
|
||||
(mapname[2]&223) == 'T' && mapname[3] == '@')
|
||||
{
|
||||
level_info_t *lev = FindLevelByWarpTrans (atoi (mapname + 4));
|
||||
if (lev != NULL)
|
||||
|
@ -1461,12 +1440,12 @@ CCMD (map)
|
|||
}
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
MapData * map = P_OpenMapData(argv[1]);
|
||||
if (map == NULL)
|
||||
if (!P_CheckMapData(argv[1]))
|
||||
{
|
||||
Printf ("No map %s\n", argv[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete map;
|
||||
G_DeferedInitNew (argv[1]);
|
||||
}
|
||||
}
|
||||
|
@ -1486,12 +1465,12 @@ CCMD (open)
|
|||
if (argv.argc() > 1)
|
||||
{
|
||||
sprintf(d_mapname, "file:%s", argv[1]);
|
||||
MapData * map = P_OpenMapData(d_mapname);
|
||||
if (map == NULL)
|
||||
if (!P_CheckMapData(d_mapname))
|
||||
{
|
||||
Printf ("No map %s\n", d_mapname);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete map;
|
||||
gameaction = ga_newgame2;
|
||||
d_skill = -1;
|
||||
}
|
||||
|
@ -1642,12 +1621,10 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
|
|||
}
|
||||
|
||||
// [RH] If this map doesn't exist, bomb out
|
||||
MapData * map = P_OpenMapData(mapname);
|
||||
if (!map)
|
||||
if (!P_CheckMapData(mapname))
|
||||
{
|
||||
I_Error ("Could not find map %s\n", mapname);
|
||||
}
|
||||
delete map;
|
||||
|
||||
oldSpeed = GameSpeed;
|
||||
wantFast = !!G_SkillProperty(SKILLP_FastMonsters);
|
||||
|
@ -1819,10 +1796,8 @@ const char *G_GetSecretExitMap()
|
|||
|
||||
if (level.secretmap[0] != 0)
|
||||
{
|
||||
MapData *map = P_OpenMapData(level.secretmap);
|
||||
if (map != NULL)
|
||||
if (P_CheckMapData(level.secretmap))
|
||||
{
|
||||
delete map;
|
||||
nextmap = level.secretmap;
|
||||
}
|
||||
}
|
||||
|
@ -2067,7 +2042,7 @@ void G_DoLoadLevel (int position, bool autosave)
|
|||
|
||||
// DOOM determines the sky texture to be used
|
||||
// depending on the current episode and the game version.
|
||||
// [RH] Fetch sky parameters from level_locals_t.
|
||||
// [RH] Fetch sky parameters from FLevelLocals.
|
||||
sky1texture = TexMan.GetTexture (level.skypic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable);
|
||||
sky2texture = TexMan.GetTexture (level.skypic2, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable);
|
||||
|
||||
|
@ -2310,9 +2285,7 @@ void G_FinishTravel ()
|
|||
|
||||
// The player being spawned here is a short lived dummy and
|
||||
// must not start any ENTER script or big problems will happen.
|
||||
P_SpawnPlayer (&playerstarts[pawn->player - players], true);
|
||||
|
||||
pawndup = pawn->player->mo;
|
||||
pawndup = P_SpawnPlayer (&playerstarts[pawn->player - players], true);
|
||||
if (!startkeepfacing)
|
||||
{
|
||||
pawn->angle = pawndup->angle;
|
||||
|
@ -2431,7 +2404,6 @@ void G_InitLevelLocals ()
|
|||
level.levelnum = info->levelnum;
|
||||
level.music = info->music;
|
||||
level.musicorder = info->musicorder;
|
||||
level.f1 = info->f1; // [RC] And import the f1 name
|
||||
|
||||
strncpy (level.level_name, info->level_name, 63);
|
||||
G_MaybeLookupLevelName (NULL);
|
||||
|
@ -2467,7 +2439,7 @@ void G_InitLevelLocals ()
|
|||
gl_SetFogParams(info->fogdensity, info->outsidefog, info->outsidefogdensity, info->skyfog);
|
||||
}
|
||||
|
||||
bool level_locals_s::IsJumpingAllowed() const
|
||||
bool FLevelLocals::IsJumpingAllowed() const
|
||||
{
|
||||
if (dmflags & DF_NO_JUMP)
|
||||
return false;
|
||||
|
@ -2476,7 +2448,7 @@ bool level_locals_s::IsJumpingAllowed() const
|
|||
return !(level.flags & LEVEL_JUMP_NO);
|
||||
}
|
||||
|
||||
bool level_locals_s::IsCrouchingAllowed() const
|
||||
bool FLevelLocals::IsCrouchingAllowed() const
|
||||
{
|
||||
if (dmflags & DF_NO_CROUCH)
|
||||
return false;
|
||||
|
@ -2485,7 +2457,7 @@ bool level_locals_s::IsCrouchingAllowed() const
|
|||
return !(level.flags & LEVEL_CROUCH_NO);
|
||||
}
|
||||
|
||||
bool level_locals_s::IsFreelookAllowed() const
|
||||
bool FLevelLocals::IsFreelookAllowed() const
|
||||
{
|
||||
if (level.flags & LEVEL_FREELOOK_NO)
|
||||
return false;
|
||||
|
@ -2544,10 +2516,8 @@ level_info_t *CheckLevelRedirect (level_info_t *info)
|
|||
if (playeringame[i] && players[i].mo->FindInventory (type))
|
||||
{
|
||||
// check for actual presence of the map.
|
||||
MapData * map = P_OpenMapData(info->RedirectMap);
|
||||
if (map != NULL)
|
||||
if (P_CheckMapData(info->RedirectMap))
|
||||
{
|
||||
delete map;
|
||||
return FindLevelInfo(info->RedirectMap);
|
||||
}
|
||||
break;
|
||||
|
@ -2634,90 +2604,6 @@ const char *G_MaybeLookupLevelName (level_info_t *ininfo)
|
|||
return info != NULL ? info->level_name : NULL;
|
||||
}
|
||||
|
||||
void G_MakeEpisodes ()
|
||||
{
|
||||
int i;
|
||||
|
||||
// Set the default episodes
|
||||
if (EpiDef.numitems == 0)
|
||||
{
|
||||
static const char eps[5][8] =
|
||||
{
|
||||
"E1M1", "E2M1", "E3M1", "E4M1", "E5M1"
|
||||
};
|
||||
static const char depinames[4][7] =
|
||||
{
|
||||
"M_EPI1", "M_EPI2", "M_EPI3", "M_EPI4"
|
||||
};
|
||||
static const char depikeys[4] = { 'k', 't', 'i', 't' };
|
||||
|
||||
static const char *hepinames[5] =
|
||||
{
|
||||
"$MNU_COTD",
|
||||
"$MNU_HELLSMAW",
|
||||
"$MNU_DOME",
|
||||
"$MNU_OSSUARY",
|
||||
"$MNU_DEMESNE",
|
||||
};
|
||||
static const char hepikeys[5] = { 'c', 'h', 'd', 'o', 's' };
|
||||
|
||||
if (gameinfo.flags & GI_MAPxx)
|
||||
{
|
||||
if (gameinfo.gametype == GAME_Hexen)
|
||||
{
|
||||
// "&wt@01" is a magic name that will become whatever map has
|
||||
// warptrans 1.
|
||||
strcpy (EpisodeMaps[0], "&wt@01");
|
||||
EpisodeMenu[0].name = copystring ("Hexen");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (EpisodeMaps[0], "MAP01");
|
||||
EpisodeMenu[0].name = copystring ("Hell on Earth");
|
||||
}
|
||||
EpisodeMenu[0].alphaKey = 'h';
|
||||
EpisodeMenu[0].fulltext = true;
|
||||
EpiDef.numitems = 1;
|
||||
}
|
||||
else if (gameinfo.gametype == GAME_Doom)
|
||||
{
|
||||
memcpy (EpisodeMaps, eps, 4*8);
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
EpisodeMenu[i].name = copystring (depinames[i]);
|
||||
EpisodeMenu[i].fulltext = false;
|
||||
EpisodeMenu[i].alphaKey = depikeys[i];
|
||||
}
|
||||
if (gameinfo.flags & GI_MENUHACK_RETAIL)
|
||||
{
|
||||
EpiDef.numitems = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
EpiDef.numitems = 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (EpisodeMaps, eps, 5*8);
|
||||
for (i = 0; i < 5; ++i)
|
||||
{
|
||||
EpisodeMenu[i].name = copystring (hepinames[i]);
|
||||
EpisodeMenu[i].fulltext = true;
|
||||
EpisodeMenu[i].alphaKey = hepikeys[i];
|
||||
}
|
||||
if (gameinfo.flags & GI_MENUHACK_EXTENDED)
|
||||
{
|
||||
EpiDef.numitems = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
EpiDef.numitems = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G_AirControlChanged ()
|
||||
{
|
||||
if (level.aircontrol <= 256)
|
||||
|
@ -3166,7 +3052,7 @@ void P_ReadACSDefereds (PNGHandle *png)
|
|||
}
|
||||
|
||||
|
||||
void level_locals_s::Tick ()
|
||||
void FLevelLocals::Tick ()
|
||||
{
|
||||
// Reset carry sectors
|
||||
if (Scrolls != NULL)
|
||||
|
@ -3175,7 +3061,7 @@ void level_locals_s::Tick ()
|
|||
}
|
||||
}
|
||||
|
||||
void level_locals_s::AddScroller (DScroller *scroller, int secnum)
|
||||
void FLevelLocals::AddScroller (DScroller *scroller, int secnum)
|
||||
{
|
||||
if (secnum < 0)
|
||||
{
|
||||
|
|
|
@ -130,7 +130,7 @@ struct FSpecialAction
|
|||
FSpecialAction *Next;
|
||||
};
|
||||
|
||||
struct level_info_s
|
||||
struct level_info_t
|
||||
{
|
||||
char mapname[9];
|
||||
int levelnum;
|
||||
|
@ -146,7 +146,7 @@ struct level_info_s
|
|||
char *level_name;
|
||||
char fadetable[9];
|
||||
SBYTE WallVertLight, WallHorizLight;
|
||||
const char *f1;
|
||||
char f1[9];
|
||||
// TheDefaultLevelInfo initializes everything above this line.
|
||||
int musicorder;
|
||||
FCompressedMemFile *snapshot;
|
||||
|
@ -172,13 +172,13 @@ struct level_info_s
|
|||
FName RedirectType;
|
||||
char RedirectMap[9];
|
||||
|
||||
char enterpic[9];
|
||||
char exitpic[9];
|
||||
char *enterpic;
|
||||
char *exitpic;
|
||||
char *intermusic;
|
||||
int intermusicorder;
|
||||
|
||||
char soundinfo[9];
|
||||
char sndseq[9];
|
||||
char *soundinfo;
|
||||
char *sndseq;
|
||||
char bordertexture[9];
|
||||
|
||||
int fogdensity;
|
||||
|
@ -187,8 +187,8 @@ struct level_info_s
|
|||
FSpecialAction * specialactions;
|
||||
|
||||
float teamdamage;
|
||||
|
||||
};
|
||||
typedef struct level_info_s level_info_t;
|
||||
|
||||
// [RH] These get zeroed every tic and are updated by thinkers.
|
||||
struct FSectorScrollValues
|
||||
|
@ -196,7 +196,7 @@ struct FSectorScrollValues
|
|||
fixed_t ScrollX, ScrollY;
|
||||
};
|
||||
|
||||
struct level_locals_s
|
||||
struct FLevelLocals
|
||||
{
|
||||
void Tick ();
|
||||
void AddScroller (DScroller *, int secnum);
|
||||
|
@ -254,15 +254,12 @@ struct level_locals_s
|
|||
|
||||
bool FromSnapshot; // The current map was restored from a snapshot
|
||||
|
||||
const char *f1;
|
||||
|
||||
float teamdamage;
|
||||
|
||||
bool IsJumpingAllowed() const;
|
||||
bool IsCrouchingAllowed() const;
|
||||
bool IsFreelookAllowed() const;
|
||||
};
|
||||
typedef struct level_locals_s level_locals_t;
|
||||
|
||||
enum EndTypes
|
||||
{
|
||||
|
@ -309,8 +306,9 @@ typedef struct cluster_info_s cluster_info_t;
|
|||
#define CLUSTER_FINALEPIC 0x00000008 // Finale "flat" is actually a full-sized image
|
||||
#define CLUSTER_LOOKUPEXITTEXT 0x00000010 // Exit text is the name of a language string
|
||||
#define CLUSTER_LOOKUPENTERTEXT 0x00000020 // Enter text is the name of a language string
|
||||
#define CLUSTER_LOOKUPNAME 0x00000040 // Name is the name of a language string
|
||||
|
||||
extern level_locals_t level;
|
||||
extern FLevelLocals level;
|
||||
|
||||
extern TArray<level_info_t> wadlevelinfos;
|
||||
|
||||
|
@ -360,7 +358,6 @@ void G_InitLevelLocals (void);
|
|||
|
||||
void G_AirControlChanged ();
|
||||
|
||||
void G_MakeEpisodes (void);
|
||||
const char *G_MaybeLookupLevelName (level_info_t *level);
|
||||
|
||||
cluster_info_t *FindClusterInfo (int cluster);
|
||||
|
|
|
@ -344,7 +344,7 @@ void P_InitKeyMessages()
|
|||
ClearLocks();
|
||||
while ((lump = Wads.FindLump ("LOCKDEFS", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump, "LOCKDEFS");
|
||||
FScanner sc(lump);
|
||||
while (sc.GetString ())
|
||||
{
|
||||
if (sc.Compare("LOCK"))
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "s_sound.h"
|
||||
#include "m_random.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "sbar.h"
|
||||
|
||||
#define MORPHTICS (40*TICRATE)
|
||||
|
||||
|
@ -56,6 +57,10 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
if (spawntype == p->mo->GetClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
morphed = static_cast<APlayerPawn *>(Spawn (spawntype, actor->x, actor->y, actor->z, NO_REPLACE));
|
||||
DObject::StaticPointerSubstitution (actor, morphed);
|
||||
|
@ -78,6 +83,18 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
|
|||
actor->flags |= MF_UNMORPHED;
|
||||
actor->renderflags |= RF_INVISIBLE;
|
||||
p->morphTics = MORPHTICS;
|
||||
|
||||
// [MH] Used by SBARINFO to speed up face drawing
|
||||
p->MorphedPlayerClass = 0;
|
||||
for (unsigned int i = 1; i < PlayerClasses.Size (); i++)
|
||||
{
|
||||
if (PlayerClasses[i].Type == spawntype)
|
||||
{
|
||||
p->MorphedPlayerClass = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p->health = morphed->health;
|
||||
p->mo = morphed;
|
||||
p->momx = p->momy = 0;
|
||||
|
@ -116,6 +133,18 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
|
|||
p->camera = morphed;
|
||||
}
|
||||
morphed->ScoreIcon = actor->ScoreIcon; // [GRB]
|
||||
|
||||
// [MH]
|
||||
// If the player that was morphed is the one
|
||||
// taking events, set up the face, if any;
|
||||
// this is only needed for old-skool skins
|
||||
// and for the original DOOM status bar.
|
||||
if ((p == &players[consoleplayer]) &&
|
||||
(strcmp(spawntype->Meta.GetMetaString (APMETA_Face), "None") != 0))
|
||||
{
|
||||
StatusBar->SetFace(&skins[p->MorphedPlayerClass]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -182,6 +211,39 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
|||
{
|
||||
player->camera = mo;
|
||||
}
|
||||
|
||||
// [MH]
|
||||
// If the player that was morphed is the one
|
||||
// taking events, reset up the face, if any;
|
||||
// this is only needed for old-skool skins
|
||||
// and for the original DOOM status bar.
|
||||
if ((player == &players[consoleplayer]) &&
|
||||
(strcmp(pmo->GetClass()->Meta.GetMetaString (APMETA_Face), "None") != 0))
|
||||
{
|
||||
// Assume root-level base skin to begin with
|
||||
size_t skinindex = 0;
|
||||
// If a custom skin was in use, then reload it
|
||||
// or else the base skin for the player class.
|
||||
if ((unsigned int)player->userinfo.skin >= PlayerClasses.Size () &&
|
||||
(size_t)player->userinfo.skin < numskins)
|
||||
{
|
||||
skinindex = player->userinfo.skin;
|
||||
}
|
||||
else if (PlayerClasses.Size () > 1)
|
||||
{
|
||||
const PClass *whatami = player->mo->GetClass();
|
||||
for (unsigned int i = 0; i < PlayerClasses.Size (); ++i)
|
||||
{
|
||||
if (PlayerClasses[i].Type == whatami)
|
||||
{
|
||||
skinindex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
StatusBar->SetFace(&skins[skinindex]);
|
||||
}
|
||||
|
||||
angle = mo->angle >> ANGLETOFINESHIFT;
|
||||
Spawn<ATeleportFog> (pmo->x + 20*finecosine[angle],
|
||||
pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE);
|
||||
|
|
|
@ -183,22 +183,24 @@ enum //drawimage flags
|
|||
|
||||
enum //drawnumber flags
|
||||
{
|
||||
DRAWNUMBER_HEALTH = 1,
|
||||
DRAWNUMBER_ARMOR = 2,
|
||||
DRAWNUMBER_AMMO1 = 4,
|
||||
DRAWNUMBER_AMMO2 = 8,
|
||||
DRAWNUMBER_AMMO = 16,
|
||||
DRAWNUMBER_AMMOCAPACITY = 32,
|
||||
DRAWNUMBER_FRAGS = 64,
|
||||
DRAWNUMBER_INVENTORY = 128,
|
||||
DRAWNUMBER_KILLS = 256,
|
||||
DRAWNUMBER_MONSTERS = 512,
|
||||
DRAWNUMBER_ITEMS = 1024,
|
||||
DRAWNUMBER_TOTALITEMS = 2048,
|
||||
DRAWNUMBER_SECRETS = 4096,
|
||||
DRAWNUMBER_TOTALSECRETS = 8192,
|
||||
DRAWNUMBER_ARMORCLASS = 16384,
|
||||
DRAWNUMBER_GLOBALVAR = 32768,
|
||||
DRAWNUMBER_HEALTH = 0x1,
|
||||
DRAWNUMBER_ARMOR = 0x2,
|
||||
DRAWNUMBER_AMMO1 = 0x4,
|
||||
DRAWNUMBER_AMMO2 = 0x8,
|
||||
DRAWNUMBER_AMMO = 0x10,
|
||||
DRAWNUMBER_AMMOCAPACITY = 0x20,
|
||||
DRAWNUMBER_FRAGS = 0x40,
|
||||
DRAWNUMBER_INVENTORY = 0x80,
|
||||
DRAWNUMBER_KILLS = 0x100,
|
||||
DRAWNUMBER_MONSTERS = 0x200,
|
||||
DRAWNUMBER_ITEMS = 0x400,
|
||||
DRAWNUMBER_TOTALITEMS = 0x800,
|
||||
DRAWNUMBER_SECRETS = 0x1000,
|
||||
DRAWNUMBER_TOTALSECRETS = 0x2000,
|
||||
DRAWNUMBER_ARMORCLASS = 0x4000,
|
||||
DRAWNUMBER_GLOBALVAR = 0x8000,
|
||||
DRAWNUMBER_GLOBALARRAY = 0x10000,
|
||||
DRAWNUMBER_FILLZEROS = 0x20000,
|
||||
};
|
||||
|
||||
enum //drawbar flags (will go into special2)
|
||||
|
@ -305,6 +307,7 @@ enum //Bar key words
|
|||
SBARINFO_GAMEMODE,
|
||||
SBARINFO_PLAYERCLASS,
|
||||
SBARINFO_ASPECTRATIO,
|
||||
SBARINFO_ISSELECTED,
|
||||
SBARINFO_WEAPONAMMO,
|
||||
SBARINFO_ININVENTORY,
|
||||
};
|
||||
|
@ -338,9 +341,9 @@ public:
|
|||
void SetMugShotState(const char* stateName, bool waitTillDone=false);
|
||||
private:
|
||||
void doCommands(SBarInfoBlock &block);
|
||||
void DrawGraphic(FTexture* texture, int x, int y, int flags);
|
||||
void DrawGraphic(FTexture* texture, int x, int y, int flags=0);
|
||||
void DrawString(const char* str, int x, int y, EColorRange translation, int spacing=0);
|
||||
void DrawNumber(int num, int len, int x, int y, EColorRange translation, int spacing=0);
|
||||
void DrawNumber(int num, int len, int x, int y, EColorRange translation, int spacing=0, bool fillzeros=false);
|
||||
void DrawFace(FString &defaultFace, int accuracy, bool xdth, bool animatedgodmode, int x, int y);
|
||||
int updateState(bool xdth, bool animatedgodmode);
|
||||
void DrawInventoryBar(int type, int num, int x, int y, bool alwaysshow,
|
||||
|
|
|
@ -559,7 +559,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
{
|
||||
DrawGraphic(TexMan[cmd.sprite], cmd.x, cmd.y, cmd.flags);
|
||||
}
|
||||
else
|
||||
else if(cmd.sprite != -1)
|
||||
{
|
||||
DrawGraphic(Images[cmd.sprite], cmd.x, cmd.y, cmd.flags);
|
||||
}
|
||||
|
@ -571,7 +571,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
{
|
||||
drawingFont = cmd.font;
|
||||
}
|
||||
if(cmd.flags == DRAWNUMBER_HEALTH)
|
||||
if(cmd.flags & DRAWNUMBER_HEALTH)
|
||||
{
|
||||
value = health;
|
||||
if(SBarInfoScript->lowerHealthCap && cmd.value < 0) //health shouldn't display negatives
|
||||
|
@ -579,11 +579,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
value = 0;
|
||||
}
|
||||
}
|
||||
else if(cmd.flags == DRAWNUMBER_ARMOR)
|
||||
else if(cmd.flags & DRAWNUMBER_ARMOR)
|
||||
{
|
||||
value = armorAmount;
|
||||
}
|
||||
else if(cmd.flags == DRAWNUMBER_AMMO1)
|
||||
else if(cmd.flags & DRAWNUMBER_AMMO1)
|
||||
{
|
||||
value = ammocount1;
|
||||
if(ammo1 == NULL) //no ammo, do not draw
|
||||
|
@ -591,7 +591,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if(cmd.flags == DRAWNUMBER_AMMO2)
|
||||
else if(cmd.flags & DRAWNUMBER_AMMO2)
|
||||
{
|
||||
value = ammocount2;
|
||||
if(ammo2 == NULL) //no ammo, do not draw
|
||||
|
@ -599,7 +599,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if(cmd.flags == DRAWNUMBER_AMMO)
|
||||
else if(cmd.flags & DRAWNUMBER_AMMO)
|
||||
{
|
||||
const PClass* ammo = PClass::FindClass(cmd.string[0]);
|
||||
AInventory* item = CPlayer->mo->FindInventory(ammo);
|
||||
|
@ -612,7 +612,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
value = 0;
|
||||
}
|
||||
}
|
||||
else if(cmd.flags == DRAWNUMBER_AMMOCAPACITY)
|
||||
else if(cmd.flags & DRAWNUMBER_AMMOCAPACITY)
|
||||
{
|
||||
const PClass* ammo = PClass::FindClass(cmd.string[0]);
|
||||
AInventory* item = CPlayer->mo->FindInventory(ammo);
|
||||
|
@ -625,21 +625,21 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
value = ((AInventory *)GetDefaultByType(ammo))->MaxAmount;
|
||||
}
|
||||
}
|
||||
else if(cmd.flags == DRAWNUMBER_FRAGS)
|
||||
else if(cmd.flags & DRAWNUMBER_FRAGS)
|
||||
value = CPlayer->fragcount;
|
||||
else if(cmd.flags == DRAWNUMBER_KILLS)
|
||||
else if(cmd.flags & DRAWNUMBER_KILLS)
|
||||
value = level.killed_monsters;
|
||||
else if(cmd.flags == DRAWNUMBER_MONSTERS)
|
||||
else if(cmd.flags & DRAWNUMBER_MONSTERS)
|
||||
value = level.total_monsters;
|
||||
else if(cmd.flags == DRAWNUMBER_ITEMS)
|
||||
else if(cmd.flags & DRAWNUMBER_ITEMS)
|
||||
value = level.found_items;
|
||||
else if(cmd.flags == DRAWNUMBER_TOTALITEMS)
|
||||
else if(cmd.flags & DRAWNUMBER_TOTALITEMS)
|
||||
value = level.total_items;
|
||||
else if(cmd.flags == DRAWNUMBER_SECRETS)
|
||||
else if(cmd.flags & DRAWNUMBER_SECRETS)
|
||||
value = level.found_secrets;
|
||||
else if(cmd.flags == DRAWNUMBER_TOTALSECRETS)
|
||||
else if(cmd.flags & DRAWNUMBER_TOTALSECRETS)
|
||||
value = level.total_secrets;
|
||||
else if(cmd.flags == DRAWNUMBER_ARMORCLASS)
|
||||
else if(cmd.flags & DRAWNUMBER_ARMORCLASS)
|
||||
{
|
||||
AHexenArmor *harmor = CPlayer->mo->FindInventory<AHexenArmor>();
|
||||
if(harmor != NULL)
|
||||
|
@ -654,9 +654,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
}
|
||||
value /= (5*FRACUNIT);
|
||||
}
|
||||
else if(cmd.flags == DRAWNUMBER_GLOBALVAR)
|
||||
else if(cmd.flags & DRAWNUMBER_GLOBALVAR)
|
||||
value = ACS_GlobalVars[cmd.value];
|
||||
else if(cmd.flags == DRAWNUMBER_INVENTORY)
|
||||
else if(cmd.flags & DRAWNUMBER_GLOBALARRAY)
|
||||
value = ACS_GlobalArrays[cmd.value][consoleplayer];
|
||||
else if(cmd.flags & DRAWNUMBER_INVENTORY)
|
||||
{
|
||||
AInventory* item = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[0]));
|
||||
if(item != NULL)
|
||||
|
@ -668,12 +670,13 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
value = 0;
|
||||
}
|
||||
}
|
||||
if(cmd.special3 != -1 && cmd.value <= cmd.special3) //low
|
||||
DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation2, cmd.special2);
|
||||
else if(cmd.special4 != -1 && cmd.value >= cmd.special4) //high
|
||||
DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation3, cmd.special2);
|
||||
bool fillzeros = !!(cmd.flags & DRAWNUMBER_FILLZEROS);
|
||||
if(cmd.special3 != -1 && value <= cmd.special3) //low
|
||||
DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation2, cmd.special2, fillzeros);
|
||||
else if(cmd.special4 != -1 && value >= cmd.special4) //high
|
||||
DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation3, cmd.special2, fillzeros);
|
||||
else
|
||||
DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation, cmd.special2);
|
||||
DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation, cmd.special2, fillzeros);
|
||||
break;
|
||||
}
|
||||
case SBARINFO_DRAWMUGSHOT:
|
||||
|
@ -1079,6 +1082,27 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
doCommands(cmd.subBlock);
|
||||
}
|
||||
break;
|
||||
case SBARINFO_ISSELECTED:
|
||||
if(CPlayer->ReadyWeapon != NULL)
|
||||
{
|
||||
const PClass *weapon1 = PClass::FindClass(cmd.string[0]);
|
||||
const PClass *weapon2 = PClass::FindClass(cmd.string[1]);
|
||||
if(weapon2 != NULL)
|
||||
{
|
||||
if((cmd.flags & SBARINFOEVENT_NOT) && (weapon1 != CPlayer->ReadyWeapon->GetSpecies() && weapon2 != CPlayer->ReadyWeapon->GetSpecies()))
|
||||
doCommands(cmd.subBlock);
|
||||
else if(!(cmd.flags & SBARINFOEVENT_NOT) && (weapon1 == CPlayer->ReadyWeapon->GetSpecies() || weapon2 == CPlayer->ReadyWeapon->GetSpecies()))
|
||||
doCommands(cmd.subBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!(cmd.flags & SBARINFOEVENT_NOT) && weapon1 == CPlayer->ReadyWeapon->GetSpecies())
|
||||
doCommands(cmd.subBlock);
|
||||
else if((cmd.flags & SBARINFOEVENT_NOT) && weapon1 != CPlayer->ReadyWeapon->GetSpecies())
|
||||
doCommands(cmd.subBlock);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SBARINFO_WEAPONAMMO:
|
||||
if(CPlayer->ReadyWeapon != NULL)
|
||||
{
|
||||
|
@ -1154,6 +1178,10 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
|||
//draws an image with the specified flags
|
||||
void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int flags)
|
||||
{
|
||||
if (texture == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if((flags & DRAWIMAGE_OFFSET_CENTER))
|
||||
{
|
||||
x -= (texture->GetWidth()/2)-texture->LeftOffset;
|
||||
|
@ -1162,8 +1190,9 @@ void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int flags)
|
|||
x += ST_X;
|
||||
y += ST_Y;
|
||||
int w = texture->GetScaledWidth();
|
||||
int h = texture->GetScaledHeight();
|
||||
int h = texture->GetScaledHeight() + y;
|
||||
screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true);
|
||||
h -= y;
|
||||
if((flags & DRAWIMAGE_TRANSLATABLE))
|
||||
{
|
||||
screen->DrawTexture(texture, x, y,
|
||||
|
@ -1224,12 +1253,27 @@ void DSBarInfo::DrawString(const char* str, int x, int y, EColorRange translatio
|
|||
}
|
||||
|
||||
//draws the specified number up to len digits
|
||||
void DSBarInfo::DrawNumber(int num, int len, int x, int y, EColorRange translation, int spacing)
|
||||
void DSBarInfo::DrawNumber(int num, int len, int x, int y, EColorRange translation, int spacing, bool fillzeros)
|
||||
{
|
||||
FString value;
|
||||
int maxval = (int) ceil(pow(10., len))-1;
|
||||
if(!fillzeros || len == 1)
|
||||
num = clamp(num, -maxval, maxval);
|
||||
else //The community wanted negatives to take the last digit, but we can only do this if there is room
|
||||
num = clamp(num, (int) -(ceil(pow(10., len-1))-1), maxval);
|
||||
value.Format("%d", num);
|
||||
if(fillzeros)
|
||||
{
|
||||
if(num < 0) //We don't want the negative just yet
|
||||
value.Format("%d", -num);
|
||||
while(fillzeros && value.Len() < (unsigned int) len)
|
||||
{
|
||||
if(num < 0 && value.Len() == (unsigned int) (len-1))
|
||||
value.Insert(0, "-");
|
||||
else
|
||||
value.Insert(0, "0");
|
||||
}
|
||||
}
|
||||
if(SBarInfoScript->spacingCharacter == '\0')
|
||||
x -= int(drawingFont->StringWidth(value)+(spacing * value.Len()));
|
||||
else //monospaced so just multiplay the character size
|
||||
|
@ -1245,7 +1289,10 @@ void DSBarInfo::DrawFace(FString &defaultFace, int accuracy, bool xdth, bool ani
|
|||
for(level = 0;CPlayer->health < (accuracy-level-1)*(CPlayer->mo->GetMaxHealth()/accuracy);level++);
|
||||
if(currentState != NULL)
|
||||
{
|
||||
FTexture *face = currentState->getCurrentFrameTexture(defaultFace, &skins[CPlayer->userinfo.skin], level, angle);
|
||||
FPlayerSkin *skin = &skins[CPlayer->morphTics ? CPlayer->MorphedPlayerClass : CPlayer->userinfo.skin];
|
||||
FTexture *face = currentState->getCurrentFrameTexture(defaultFace, skin, level, angle);
|
||||
if (face != NULL)
|
||||
{
|
||||
x += ST_X;
|
||||
y += ST_Y;
|
||||
int w = face->GetScaledWidth();
|
||||
|
@ -1256,6 +1303,7 @@ void DSBarInfo::DrawFace(FString &defaultFace, int accuracy, bool xdth, bool ani
|
|||
DTA_DestHeight, h,
|
||||
TAG_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DSBarInfo::updateState(bool xdth, bool animatedgodmode)
|
||||
|
@ -1391,7 +1439,7 @@ void DSBarInfo::DrawInventoryBar(int type, int num, int x, int y, bool alwayssho
|
|||
{
|
||||
if(drawArtiboxes)
|
||||
{
|
||||
DrawImage (Images[invBarOffset + imgARTIBOX], x+i*31, y);
|
||||
DrawGraphic(Images[invBarOffset + imgARTIBOX], x+i*31, y);
|
||||
}
|
||||
DrawDimImage (TexMan(item->Icon), x+i*31, y, item->Amount <= 0);
|
||||
if(alwaysshowcounter || item->Amount != 1)
|
||||
|
@ -1402,28 +1450,28 @@ void DSBarInfo::DrawInventoryBar(int type, int num, int x, int y, bool alwayssho
|
|||
{
|
||||
if(type == GAME_Heretic)
|
||||
{
|
||||
DrawImage(Images[invBarOffset + imgSELECTBOX], x+i*31, y+29);
|
||||
DrawGraphic(Images[invBarOffset + imgSELECTBOX], x+i*31, y+29);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawImage(Images[invBarOffset + imgSELECTBOX], x+i*31, y);
|
||||
DrawGraphic(Images[invBarOffset + imgSELECTBOX], x+i*31, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; i < num && drawArtiboxes; ++i)
|
||||
{
|
||||
DrawImage (Images[invBarOffset + imgARTIBOX], x+i*31, y);
|
||||
DrawGraphic(Images[invBarOffset + imgARTIBOX], x+i*31, y);
|
||||
}
|
||||
// Is there something to the left?
|
||||
if (!noArrows && CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst)
|
||||
{
|
||||
DrawImage (Images[!(gametic & 4) ?
|
||||
DrawGraphic(Images[!(gametic & 4) ?
|
||||
invBarOffset + imgINVLFGEM1 : invBarOffset + imgINVLFGEM2], x-12, y);
|
||||
}
|
||||
// Is there something to the right?
|
||||
if (!noArrows && item != NULL)
|
||||
{
|
||||
DrawImage (Images[!(gametic & 4) ?
|
||||
DrawGraphic(Images[!(gametic & 4) ?
|
||||
invBarOffset + imgINVRTGEM1 : invBarOffset + imgINVRTGEM2], x+num*31+2, y);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ static const char *SBarInfoRoutineLevel[] =
|
|||
"gamemode",
|
||||
"playerclass",
|
||||
"aspectratio",
|
||||
"isselected",
|
||||
"weaponammo", //event
|
||||
"ininventory",
|
||||
NULL
|
||||
|
@ -130,17 +131,14 @@ void SBarInfo::ParseSBarInfo(int lump)
|
|||
{
|
||||
gameType = gameinfo.gametype;
|
||||
bool baseSet = false;
|
||||
FScanner sc(lump, Wads.GetLumpFullName(lump));
|
||||
FScanner sc(lump);
|
||||
sc.SetCMode(true);
|
||||
while(sc.CheckToken(TK_Identifier) || sc.CheckToken(TK_Include))
|
||||
{
|
||||
if(sc.TokenType == TK_Include)
|
||||
{
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
int lump = Wads.CheckNumForFullName(sc.String); //zip/pk3
|
||||
//Do a normal wad lookup.
|
||||
if (lump == -1 && sc.StringLen <= 8 && !strchr(sc.String, '/'))
|
||||
lump = Wads.CheckNumForName(sc.String);
|
||||
int lump = Wads.CheckNumForFullName(sc.String, true);
|
||||
if (lump == -1)
|
||||
sc.ScriptError("Lump '%s' not found", sc.String);
|
||||
ParseSBarInfo(lump);
|
||||
|
@ -493,6 +491,14 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
|||
sc.ScriptError("Global variable number out of range: %d", sc.Number);
|
||||
cmd.value = sc.Number;
|
||||
}
|
||||
else if(sc.Compare("globalarray")) //acts like variable[playernumber()]
|
||||
{
|
||||
cmd.flags += DRAWNUMBER_GLOBALARRAY;
|
||||
sc.MustGetToken(TK_IntConst);
|
||||
if(sc.Number < 0 || sc.Number >= NUM_GLOBALVARS)
|
||||
sc.ScriptError("Global variable number out of range: %d", sc.Number);
|
||||
cmd.value = sc.Number;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.flags = DRAWNUMBER_INVENTORY;
|
||||
|
@ -506,6 +512,18 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
|||
}
|
||||
sc.MustGetToken(',');
|
||||
}
|
||||
while(sc.CheckToken(TK_Identifier))
|
||||
{
|
||||
if(sc.Compare("fillzeros"))
|
||||
{
|
||||
cmd.flags += DRAWNUMBER_FILLZEROS;
|
||||
Printf("%d", cmd.flags);
|
||||
}
|
||||
else
|
||||
sc.ScriptError("Unknown flag '%s'.", sc.String);
|
||||
if(!sc.CheckToken('|'))
|
||||
sc.MustGetToken(',');
|
||||
}
|
||||
this->getCoordinates(sc, cmd);
|
||||
if(sc.CheckToken(','))
|
||||
{
|
||||
|
@ -951,6 +969,33 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
|||
sc.MustGetToken('{');
|
||||
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
||||
break;
|
||||
case SBARINFO_ISSELECTED:
|
||||
if(sc.CheckToken(TK_Identifier))
|
||||
{
|
||||
if(sc.Compare("not"))
|
||||
{
|
||||
cmd.flags += SBARINFOEVENT_NOT;
|
||||
}
|
||||
else
|
||||
sc.ScriptError("Expected 'not' got '%s' instead.", sc.String);
|
||||
}
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
for(int i = 0;i < 2;i++)
|
||||
{
|
||||
cmd.setString(sc, sc.String, i);
|
||||
const PClass* item = PClass::FindClass(sc.String);
|
||||
if(item == NULL || !RUNTIME_CLASS(AWeapon)->IsAncestorOf(item))
|
||||
{
|
||||
sc.ScriptError("'%s' is not a type of weapon.", sc.String);
|
||||
}
|
||||
if(sc.CheckToken(','))
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
else
|
||||
break;
|
||||
}
|
||||
sc.MustGetToken('{');
|
||||
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
||||
break;
|
||||
case SBARINFO_WEAPONAMMO:
|
||||
sc.MustGetToken(TK_Identifier);
|
||||
if(sc.Compare("not"))
|
||||
|
@ -983,7 +1028,6 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
|||
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
||||
break;
|
||||
case SBARINFO_ININVENTORY:
|
||||
{
|
||||
sc.MustGetToken(TK_Identifier);
|
||||
if(sc.Compare("not"))
|
||||
{
|
||||
|
@ -1015,7 +1059,6 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
|||
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
block.commands.Push(cmd);
|
||||
}
|
||||
sc.MustGetToken('}');
|
||||
|
|
|
@ -928,7 +928,7 @@ void HUD_InitHud()
|
|||
|
||||
while ((lump = Wads.FindLump ("ALTHUDCF", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump, "ALTHUDCF");
|
||||
FScanner sc(lump);
|
||||
while (sc.GetString())
|
||||
{
|
||||
if (sc.Compare("Health"))
|
||||
|
|
|
@ -543,7 +543,7 @@ void A_KlaxonBlare (AActor *self)
|
|||
A_TurretLook (self);
|
||||
if (self->target == NULL)
|
||||
{
|
||||
self->SetState (self->SpawnState);
|
||||
self->SetIdle();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -210,7 +210,7 @@ void A_JabDagger (AActor *actor)
|
|||
|
||||
angle = actor->angle + (pr_jabdagger.Random2() << 18);
|
||||
pitch = P_AimLineAttack (actor, angle, 80*FRACUNIT);
|
||||
P_LineAttack (actor, angle, 80*FRACUNIT, pitch, damage, NAME_Melee, RUNTIME_CLASS(AStrifeSpark));
|
||||
P_LineAttack (actor, angle, 80*FRACUNIT, pitch, damage, NAME_Melee, RUNTIME_CLASS(AStrifeSpark), true);
|
||||
|
||||
// turn to face target
|
||||
if (linetarget)
|
||||
|
@ -934,7 +934,7 @@ void A_RocketInFlight (AActor *self)
|
|||
AActor *trail;
|
||||
|
||||
S_Sound (self, CHAN_VOICE, "misc/missileinflight", 1, ATTN_NORM);
|
||||
P_SpawnPuff (RUNTIME_CLASS(AMiniMissilePuff), self->x, self->y, self->z, self->angle - ANGLE_180, 2, true);
|
||||
P_SpawnPuff (RUNTIME_CLASS(AMiniMissilePuff), self->x, self->y, self->z, self->angle - ANGLE_180, 2, PF_HITTHING);
|
||||
trail = Spawn<ARocketTrail> (self->x - self->momx, self->y - self->momy, self->z, ALLOW_REPLACE);
|
||||
if (trail != NULL)
|
||||
{
|
||||
|
|
|
@ -1126,7 +1126,7 @@ void gl_DoParseDefs(FScanner &sc, int workingLump)
|
|||
if (lump==-1)
|
||||
sc.ScriptError("Lump '%s' not found", sc.String);
|
||||
|
||||
FScanner newscanner(lump, sc.String);
|
||||
FScanner newscanner(lump);
|
||||
gl_DoParseDefs(newscanner, lump);
|
||||
break;
|
||||
}
|
||||
|
@ -1186,7 +1186,7 @@ void gl_LoadDynLightDefs(char * defsLump)
|
|||
lastLump = 0;
|
||||
while ((workingLump = Wads.FindLump(defsLump, &lastLump)) != -1)
|
||||
{
|
||||
FScanner sc(workingLump, defsLump);
|
||||
FScanner sc(workingLump);
|
||||
gl_DoParseDefs(sc, workingLump);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -247,7 +247,7 @@ void gl_InitModels()
|
|||
memset(&smf, 0, sizeof(smf));
|
||||
while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1)
|
||||
{
|
||||
FScanner sc(Lump, "MODELDEF");
|
||||
FScanner sc(Lump);
|
||||
while (sc.GetString())
|
||||
{
|
||||
if (sc.Compare("model"))
|
||||
|
|
|
@ -112,9 +112,9 @@ static void DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed_t sy,
|
|||
else
|
||||
{
|
||||
fU2=pti->GetUL();
|
||||
fV2=pti->GetVT();
|
||||
fV1=pti->GetVT();
|
||||
fU1=pti->GetUR();
|
||||
fV1=pti->GetVB();
|
||||
fV2=pti->GetVB();
|
||||
}
|
||||
|
||||
gl.Begin(GL_TRIANGLE_STRIP);
|
||||
|
|
|
@ -247,6 +247,7 @@ enum
|
|||
ADEF_PlayerPawn_CrouchSprite,
|
||||
ADEF_PlayerPawn_DisplayName,
|
||||
ADEF_PlayerPawn_SoundClass,
|
||||
ADEF_PlayerPawn_Face,
|
||||
ADEF_PlayerPawn_ScoreIcon,
|
||||
ADEF_PlayerPawn_MorphWeapon,
|
||||
ADEF_LastString = ADEF_PlayerPawn_MorphWeapon,
|
||||
|
|
|
@ -328,6 +328,9 @@ static void ApplyActorDefault (int defnum, const char *datastr, int dataint)
|
|||
case ADEF_PlayerPawn_SoundClass:
|
||||
sgClass->Meta.SetMetaString (APMETA_SoundClass, datastr);
|
||||
break;
|
||||
case ADEF_PlayerPawn_Face:
|
||||
sgClass->Meta.SetMetaString (APMETA_Face, datastr);
|
||||
break;
|
||||
case ADEF_PlayerPawn_ScoreIcon:
|
||||
player->ScoreIcon = TexMan.AddPatch (datastr);
|
||||
if (player->ScoreIcon <= 0)
|
||||
|
|
|
@ -218,8 +218,9 @@ public:
|
|||
#define PROP_PlayerPawn_CrouchSprite(x) ADD_STRING_PROP(ADEF_PlayerPawn_CrouchSprite,"\24",x)
|
||||
#define PROP_PlayerPawn_DisplayName(x) ADD_STRING_PROP(ADEF_PlayerPawn_DisplayName,"\25",x)
|
||||
#define PROP_PlayerPawn_SoundClass(x) ADD_STRING_PROP(ADEF_PlayerPawn_SoundClass,"\26",x)
|
||||
#define PROP_PlayerPawn_ScoreIcon(x) ADD_STRING_PROP(ADEF_PlayerPawn_ScoreIcon,"\27",x)
|
||||
#define PROP_PlayerPawn_MorphWeapon(x) ADD_STRING_PROP(ADEF_PlayerPawn_MorphWeapon,"\30",x)
|
||||
#define PROP_PlayerPawn_Face(x) ADD_STRING_PROP(ADEF_PlayerPawn_Face,"\27",x) // Octal - 'tis quaint!
|
||||
#define PROP_PlayerPawn_ScoreIcon(x) ADD_STRING_PROP(ADEF_PlayerPawn_ScoreIcon,"\30",x)
|
||||
#define PROP_PlayerPawn_MorphWeapon(x) ADD_STRING_PROP(ADEF_PlayerPawn_MorphWeapon,"\31",x)
|
||||
|
||||
#define PROP_XScale(x) ADD_LONG_PROP(ADEF_XScale,x)
|
||||
#define PROP_YScale(x) ADD_LONG_PROP(ADEF_YScale,x)
|
||||
|
|
|
@ -1446,7 +1446,7 @@ void M_QuickLoad ()
|
|||
//
|
||||
void M_DrawReadThis ()
|
||||
{
|
||||
FTexture *tex, *prevpic = NULL;
|
||||
FTexture *tex = NULL, *prevpic = NULL;
|
||||
fixed_t alpha;
|
||||
|
||||
if (gameinfo.flags & GI_INFOINDEXED)
|
||||
|
@ -1463,11 +1463,15 @@ void M_DrawReadThis ()
|
|||
}
|
||||
else
|
||||
{
|
||||
tex = TexMan[gameinfo.info.infoPage[InfoType-1]];
|
||||
// Did the mapper choose a custom help page via MAPINFO?
|
||||
if((level.f1 != NULL) && (strlen(level.f1) > 0))
|
||||
if (level.info->f1[0] != 0)
|
||||
{
|
||||
tex = TexMan.FindTexture(level.f1);
|
||||
tex = TexMan.FindTexture(level.info->f1);
|
||||
}
|
||||
|
||||
if (tex == NULL)
|
||||
{
|
||||
tex = TexMan[gameinfo.info.infoPage[InfoType-1]];
|
||||
}
|
||||
|
||||
if (InfoType > 1)
|
||||
|
|
|
@ -492,6 +492,13 @@ static value_t ColumnMethods[] = {
|
|||
{ 1.0, "Optimized" }
|
||||
};
|
||||
|
||||
static value_t RocketTrailTypes[] = {
|
||||
{ 0.0, "Off" },
|
||||
{ 1.0, "Particles" },
|
||||
{ 2.0, "Sprites" },
|
||||
{ 3.0, "Sprites & Particles" }
|
||||
};
|
||||
|
||||
static value_t BloodTypes[] = {
|
||||
{ 0.0, "Sprites" },
|
||||
{ 1.0, "Sprites & Particles" },
|
||||
|
@ -540,7 +547,7 @@ static menuitem_t VideoItems[] = {
|
|||
#endif
|
||||
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
|
||||
{ discrete, "Use fuzz effect", {&r_drawfuzz}, {2.0}, {0.0}, {0.0}, {YesNo} },
|
||||
{ discrete, "Rocket Trails", {&cl_rockettrails}, {2.0}, {0.0}, {0.0}, {OnOff} },
|
||||
{ discrete, "Rocket Trails", {&cl_rockettrails}, {4.0}, {0.0}, {0.0}, {RocketTrailTypes} },
|
||||
{ discrete, "Blood Type", {&cl_bloodtype}, {3.0}, {0.0}, {0.0}, {BloodTypes} },
|
||||
{ discrete, "Bullet Puff Type", {&cl_pufftype}, {2.0}, {0.0}, {0.0}, {PuffTypes} },
|
||||
};
|
||||
|
@ -1285,7 +1292,6 @@ static menu_t SoundMenu =
|
|||
*
|
||||
*=======================================*/
|
||||
|
||||
EXTERN_CVAR (Bool, opl_enable)
|
||||
EXTERN_CVAR (Bool, opl_onechip)
|
||||
|
||||
static menuitem_t AdvSoundItems[] =
|
||||
|
@ -3465,7 +3471,7 @@ void InitCrosshairsList()
|
|||
|
||||
while ((lump = Wads.FindLump("XHAIRS", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump, "XHAIRS");
|
||||
FScanner sc(lump);
|
||||
while (sc.GetNumber())
|
||||
{
|
||||
value.value = float(sc.Number);
|
||||
|
|
|
@ -140,6 +140,7 @@ xx(Crush)
|
|||
xx(Yes)
|
||||
xx(No)
|
||||
xx(Greetings)
|
||||
xx(Idle)
|
||||
|
||||
// Compatible death names for the decorate parser.
|
||||
xx(XDeath)
|
||||
|
|
|
@ -75,17 +75,6 @@ Revision History:
|
|||
#endif
|
||||
|
||||
|
||||
/* output final shift */
|
||||
#if (OPL_SAMPLE_BITS==16)
|
||||
#define FINAL_SH (0)
|
||||
#define MAXOUT (+32767)
|
||||
#define MINOUT (-32768)
|
||||
#else
|
||||
#define FINAL_SH (8)
|
||||
#define MAXOUT (+127)
|
||||
#define MINOUT (-128)
|
||||
#endif
|
||||
|
||||
#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
|
||||
#define EG_SH 16 /* 16.16 fixed point (EG timing) */
|
||||
#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
#include "zstring.h"
|
||||
|
||||
/* select output bits size of output : 8 or 16 */
|
||||
#define OPL_SAMPLE_BITS 16
|
||||
// Multiplying OPL_SAMPLE_RATE by ADLIB_CLOCK_MUL gives the number
|
||||
// Adlib clocks per second, as used by the RAWADATA file format.
|
||||
|
||||
/* compiler dependence */
|
||||
#ifndef OSD_CPU_H
|
||||
|
@ -17,13 +17,6 @@ typedef signed short INT16; /* signed 16bit */
|
|||
typedef signed int INT32; /* signed 32bit */
|
||||
#endif
|
||||
|
||||
#if (OPL_SAMPLE_BITS==16)
|
||||
typedef INT16 OPLSAMPLE;
|
||||
#endif
|
||||
#if (OPL_SAMPLE_BITS==8)
|
||||
typedef INT8 OPLSAMPLE;
|
||||
#endif
|
||||
|
||||
|
||||
typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
|
||||
typedef void (*OPL_IRQHANDLER)(int param,int irq);
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* Name: MUS Playing kernel
|
||||
* Project: MUS File Player Library
|
||||
* Version: 1.70
|
||||
* Author: Vladimir Arnost (QA-Software)
|
||||
* Last revision: Oct-28-1995
|
||||
* Compiler: Borland C++ 3.1, Watcom C/C++ 10.0
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Revision History:
|
||||
*
|
||||
* Aug-8-1994 V1.00 V.Arnost
|
||||
* Written from scratch
|
||||
* Aug-9-1994 V1.10 V.Arnost
|
||||
* Some minor changes to improve sound quality. Tried to add
|
||||
* stereo sound capabilities, but failed to -- my SB Pro refuses
|
||||
* to switch to stereo mode.
|
||||
* Aug-13-1994 V1.20 V.Arnost
|
||||
* Stereo sound fixed. Now works also with Sound Blaster Pro II
|
||||
* (chip OPL3 -- gives 18 "stereo" (ahem) channels).
|
||||
* Changed code to handle properly notes without volume.
|
||||
* (Uses previous volume on given channel.)
|
||||
* Added cyclic channel usage to avoid annoying clicking noise.
|
||||
* Aug-17-1994 V1.30 V.Arnost
|
||||
* Completely rewritten time synchronization. Now the player runs
|
||||
* on IRQ 8 (RTC Clock - 1024 Hz).
|
||||
* Aug-28-1994 V1.40 V.Arnost
|
||||
* Added Adlib and SB Pro II detection.
|
||||
* Fixed bug that caused high part of 32-bit registers (EAX,EBX...)
|
||||
* to be corrupted.
|
||||
* Oct-30-1994 V1.50 V.Arnost
|
||||
* Tidied up the source code
|
||||
* Added C key - invoke COMMAND.COM
|
||||
* Added RTC timer interrupt flag check (0000:04A0)
|
||||
* Added BLASTER environment variable parsing
|
||||
* FIRST PUBLIC RELEASE
|
||||
* Apr-16-1995 V1.60 V.Arnost
|
||||
* Moved into separate source file MUSLIB.C
|
||||
* May-01-1995 V1.61 V.Arnost
|
||||
* Added system timer (IRQ 0) support
|
||||
* Jul-12-1995 V1.62 V.Arnost
|
||||
* OPL2/OPL3-specific code moved to module MLOPL.C
|
||||
* Module MUSLIB.C renamed to MLKERNEL.C
|
||||
* Aug-04-1995 V1.63 V.Arnost
|
||||
* Fixed stack-related bug occuring in big-code models in Watcom C
|
||||
* Aug-16-1995 V1.64 V.Arnost
|
||||
* Stack size changed from 256 to 512 words because of stack
|
||||
* underflows caused by AWE32 driver
|
||||
* Aug-28-1995 V1.65 V.Arnost
|
||||
* Fixed a serious bug that caused the player to generate an
|
||||
* exception in AWE32 driver under DOS/4GW: Register ES contained
|
||||
* garbage instead of DGROUP. The compiler-generated prolog of
|
||||
* interrupt handlers doesn't set ES register at all, thus any
|
||||
* STOS/MOVS/SCAS/CMPS instruction used within the int. handler
|
||||
* crashes the program.
|
||||
* Oct-28-1995 V1.70 V.Arnost
|
||||
* System-specific timer code moved separate modules
|
||||
*/
|
||||
|
||||
#include "muslib.h"
|
||||
|
||||
|
||||
char MLversion[] = "MUS Lib V"MLVERSIONSTR;
|
||||
char MLcopyright[] = "Copyright (c) 1994-1996 QA-Software";
|
||||
|
||||
/* Program */
|
||||
int musicBlock::playTick()
|
||||
{
|
||||
int delay = 0;
|
||||
|
||||
while (delay == 0)
|
||||
{
|
||||
uchar data = *score++;
|
||||
uchar command = (data >> 4) & 7;
|
||||
uchar channel = data & 0x0F;
|
||||
uchar last = data & 0x80;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case 0: // release note
|
||||
playingcount--;
|
||||
OPLreleaseNote(channel, *score++);
|
||||
break;
|
||||
case 1: { // play note
|
||||
uchar note = *score++;
|
||||
playingcount++;
|
||||
if (note & 0x80) // note with volume
|
||||
OPLplayNote(channel, note & 0x7F, *score++);
|
||||
else
|
||||
OPLplayNote(channel, note, -1);
|
||||
} break;
|
||||
case 2: // pitch wheel
|
||||
// MUS pitch wheel is 8 bits, but MIDI is 14
|
||||
OPLpitchWheel(channel, *score++ << (14 - 8));
|
||||
break;
|
||||
case 3: // system event (valueless controller)
|
||||
OPLchangeControl(channel, *score++, 0);
|
||||
break;
|
||||
case 4: { // change control
|
||||
uchar ctrl = *score++;
|
||||
uchar value = *score++;
|
||||
OPLchangeControl(channel, ctrl, value);
|
||||
} break;
|
||||
case 6: // end
|
||||
return 0;
|
||||
case 5: // ???
|
||||
case 7: // ???
|
||||
break;
|
||||
}
|
||||
if (last)
|
||||
{
|
||||
uchar t;
|
||||
|
||||
do
|
||||
{
|
||||
t = *score++;
|
||||
delay = (delay << 7) | (t & 127);
|
||||
} while (t & 128);
|
||||
}
|
||||
}
|
||||
return delay;
|
||||
}
|
|
@ -44,6 +44,18 @@
|
|||
#include "muslib.h"
|
||||
#include "fmopl.h"
|
||||
|
||||
OPLio::~OPLio()
|
||||
{
|
||||
}
|
||||
|
||||
void OPLio::SetClockRate(double samples_per_tick)
|
||||
{
|
||||
}
|
||||
|
||||
void OPLio::WriteDelay(int ticks)
|
||||
{
|
||||
}
|
||||
|
||||
void OPLio::OPLwriteReg(int which, uint reg, uchar data)
|
||||
{
|
||||
YM3812Write (which, 0, reg);
|
||||
|
@ -106,64 +118,73 @@ static WORD frequencies[] =
|
|||
0x1d9, 0x1da, 0x1db, 0x1dc, 0x1dd, 0x1de, 0x1de, 0x1df, 0x1e0, 0x1e1, 0x1e2, 0x1e3,
|
||||
0x1e4, 0x1e5, 0x1e5, 0x1e6, 0x1e7, 0x1e8, 0x1e9, 0x1ea, 0x1eb, 0x1ec, 0x1ed, 0x1ed,
|
||||
0x1ee, 0x1ef, 0x1f0, 0x1f1, 0x1f2, 0x1f3, 0x1f4, 0x1f5, 0x1f6, 0x1f6, 0x1f7, 0x1f8,
|
||||
0x1f9, 0x1fa, 0x1fb, 0x1fc, 0x1fd, 0x1fe, 0x1ff, 0x200, 0x201, 0x201, 0x202, 0x203,
|
||||
0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20a, 0x20b, 0x20c, 0x20d, 0x20e, 0x20f,
|
||||
0x210, 0x210, 0x211, 0x212, 0x213, 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21a,
|
||||
0x21b, 0x21c, 0x21d, 0x21e, 0x21f, 0x220, 0x221, 0x222, 0x223, 0x224, 0x225, 0x226,
|
||||
0x227, 0x228, 0x229, 0x22a, 0x22b, 0x22c, 0x22d, 0x22e, 0x22f, 0x230, 0x231, 0x232,
|
||||
0x233, 0x234, 0x235, 0x236, 0x237, 0x238, 0x239, 0x23a, 0x23b, 0x23c, 0x23d, 0x23e,
|
||||
0x23f, 0x240, 0x241, 0x242, 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24a, 0x24b,
|
||||
0x24c, 0x24d, 0x24e, 0x24f, 0x250, 0x251, 0x252, 0x253, 0x254, 0x256, 0x257, 0x258,
|
||||
0x259, 0x25a, 0x25b, 0x25c, 0x25d, 0x25e, 0x25f, 0x260, 0x262, 0x263, 0x264, 0x265,
|
||||
0x266, 0x267, 0x268, 0x269, 0x26a, 0x26c, 0x26d, 0x26e, 0x26f, 0x270, 0x271, 0x272,
|
||||
0x273, 0x275, 0x276, 0x277, 0x278, 0x279, 0x27a, 0x27b, 0x27d, 0x27e, 0x27f, 0x280,
|
||||
0x281, 0x282, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28b, 0x28c, 0x28d, 0x28e,
|
||||
0x28f, 0x290, 0x292, 0x293, 0x294, 0x295, 0x296, 0x298, 0x299, 0x29a, 0x29b, 0x29c,
|
||||
0x29e, 0x29f, 0x2a0, 0x2a1, 0x2a2, 0x2a4, 0x2a5, 0x2a6, 0x2a7, 0x2a9, 0x2aa, 0x2ab,
|
||||
0x2ac, 0x2ae, 0x2af, 0x2b0, 0x2b1, 0x2b2, 0x2b4, 0x2b5, 0x2b6, 0x2b7, 0x2b9, 0x2ba,
|
||||
0x2bb, 0x2bd, 0x2be, 0x2bf, 0x2c0, 0x2c2, 0x2c3, 0x2c4, 0x2c5, 0x2c7, 0x2c8, 0x2c9,
|
||||
0x2cb, 0x2cc, 0x2cd, 0x2ce, 0x2d0, 0x2d1, 0x2d2, 0x2d4, 0x2d5, 0x2d6, 0x2d8, 0x2d9,
|
||||
0x2da, 0x2dc, 0x2dd, 0x2de, 0x2e0, 0x2e1, 0x2e2, 0x2e4, 0x2e5, 0x2e6, 0x2e8, 0x2e9,
|
||||
0x2ea, 0x2ec, 0x2ed, 0x2ee, 0x2f0, 0x2f1, 0x2f2, 0x2f4, 0x2f5, 0x2f6, 0x2f8, 0x2f9,
|
||||
0x2fb, 0x2fc, 0x2fd, 0x2ff, 0x300, 0x302, 0x303, 0x304, 0x306, 0x307, 0x309, 0x30a,
|
||||
0x30b, 0x30d, 0x30e, 0x310, 0x311, 0x312, 0x314, 0x315, 0x317, 0x318, 0x31a, 0x31b,
|
||||
0x31c, 0x31e, 0x31f, 0x321, 0x322, 0x324, 0x325, 0x327, 0x328, 0x329, 0x32b, 0x32c,
|
||||
0x32e, 0x32f, 0x331, 0x332, 0x334, 0x335, 0x337, 0x338, 0x33a, 0x33b, 0x33d, 0x33e,
|
||||
0x340, 0x341, 0x343, 0x344, 0x346, 0x347, 0x349, 0x34a, 0x34c, 0x34d, 0x34f, 0x350,
|
||||
0x352, 0x353, 0x355, 0x357, 0x358, 0x35a, 0x35b, 0x35d, 0x35e, 0x360, 0x361, 0x363,
|
||||
0x365, 0x366, 0x368, 0x369, 0x36b, 0x36c, 0x36e, 0x370, 0x371, 0x373, 0x374, 0x376,
|
||||
0x378, 0x379, 0x37b, 0x37c, 0x37e, 0x380, 0x381, 0x383, 0x384, 0x386, 0x388, 0x389,
|
||||
0x38b, 0x38d, 0x38e, 0x390, 0x392, 0x393, 0x395, 0x397, 0x398, 0x39a, 0x39c, 0x39d,
|
||||
0x39f, 0x3a1, 0x3a2, 0x3a4, 0x3a6, 0x3a7, 0x3a9, 0x3ab, 0x3ac, 0x3ae, 0x3b0, 0x3b1,
|
||||
0x3b3, 0x3b5, 0x3b7, 0x3b8, 0x3ba, 0x3bc, 0x3bd, 0x3bf, 0x3c1, 0x3c3, 0x3c4, 0x3c6,
|
||||
0x3c8, 0x3ca, 0x3cb, 0x3cd, 0x3cf, 0x3d1, 0x3d2, 0x3d4, 0x3d6, 0x3d8, 0x3da, 0x3db,
|
||||
0x3dd, 0x3df, 0x3e1, 0x3e3, 0x3e4, 0x3e6, 0x3e8, 0x3ea, 0x3ec, 0x3ed, 0x3ef, 0x3f1,
|
||||
0x3f3, 0x3f5, 0x3f6, 0x3f8, 0x3fa, 0x3fc, 0x3fe, 0x36c, 0x388
|
||||
0x1f9, 0x1fa, 0x1fb, 0x1fc, 0x1fd, 0x1fe, 0x1ff, 0x200,
|
||||
|
||||
0x201, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20a, 0x20b, 0x20c, 0x20d, 0x20e, 0x20f,
|
||||
0x210, 0x210, 0x211, 0x212, 0x213, 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21a, 0x21b, 0x21c, 0x21d, 0x21e,
|
||||
|
||||
0x21f, 0x220, 0x221, 0x222, 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22a, 0x22b, 0x22c, 0x22d, 0x22e,
|
||||
0x22f, 0x230, 0x231, 0x232, 0x233, 0x234, 0x235, 0x236, 0x237, 0x238, 0x239, 0x23a, 0x23b, 0x23c, 0x23d, 0x23e,
|
||||
|
||||
0x23f, 0x240, 0x241, 0x242, 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24a, 0x24b, 0x24c, 0x24d, 0x24e, 0x24f,
|
||||
0x250, 0x251, 0x252, 0x253, 0x254, 0x256, 0x257, 0x258, 0x259, 0x25a, 0x25b, 0x25c, 0x25d, 0x25e, 0x25f, 0x260,
|
||||
|
||||
0x262, 0x263, 0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26a, 0x26c, 0x26d, 0x26e, 0x26f, 0x270, 0x271, 0x272,
|
||||
0x273, 0x275, 0x276, 0x277, 0x278, 0x279, 0x27a, 0x27b, 0x27d, 0x27e, 0x27f, 0x280, 0x281, 0x282, 0x284, 0x285,
|
||||
|
||||
0x286, 0x287, 0x288, 0x289, 0x28b, 0x28c, 0x28d, 0x28e, 0x28f, 0x290, 0x292, 0x293, 0x294, 0x295, 0x296, 0x298,
|
||||
0x299, 0x29a, 0x29b, 0x29c, 0x29e, 0x29f, 0x2a0, 0x2a1, 0x2a2, 0x2a4, 0x2a5, 0x2a6, 0x2a7, 0x2a9, 0x2aa, 0x2ab,
|
||||
|
||||
0x2ac, 0x2ae, 0x2af, 0x2b0, 0x2b1, 0x2b2, 0x2b4, 0x2b5, 0x2b6, 0x2b7, 0x2b9, 0x2ba, 0x2bb, 0x2bd, 0x2be, 0x2bf,
|
||||
0x2c0, 0x2c2, 0x2c3, 0x2c4, 0x2c5, 0x2c7, 0x2c8, 0x2c9, 0x2cb, 0x2cc, 0x2cd, 0x2ce, 0x2d0, 0x2d1, 0x2d2, 0x2d4,
|
||||
|
||||
0x2d5, 0x2d6, 0x2d8, 0x2d9, 0x2da, 0x2dc, 0x2dd, 0x2de, 0x2e0, 0x2e1, 0x2e2, 0x2e4, 0x2e5, 0x2e6, 0x2e8, 0x2e9,
|
||||
0x2ea, 0x2ec, 0x2ed, 0x2ee, 0x2f0, 0x2f1, 0x2f2, 0x2f4, 0x2f5, 0x2f6, 0x2f8, 0x2f9, 0x2fb, 0x2fc, 0x2fd, 0x2ff,
|
||||
|
||||
0x300, 0x302, 0x303, 0x304, 0x306, 0x307, 0x309, 0x30a, 0x30b, 0x30d, 0x30e, 0x310, 0x311, 0x312, 0x314, 0x315,
|
||||
0x317, 0x318, 0x31a, 0x31b, 0x31c, 0x31e, 0x31f, 0x321, 0x322, 0x324, 0x325, 0x327, 0x328, 0x329, 0x32b, 0x32c,
|
||||
|
||||
0x32e, 0x32f, 0x331, 0x332, 0x334, 0x335, 0x337, 0x338, 0x33a, 0x33b, 0x33d, 0x33e, 0x340, 0x341, 0x343, 0x344,
|
||||
0x346, 0x347, 0x349, 0x34a, 0x34c, 0x34d, 0x34f, 0x350, 0x352, 0x353, 0x355, 0x357, 0x358, 0x35a, 0x35b, 0x35d,
|
||||
|
||||
0x35e, 0x360, 0x361, 0x363, 0x365, 0x366, 0x368, 0x369, 0x36b, 0x36c, 0x36e, 0x370, 0x371, 0x373, 0x374, 0x376,
|
||||
0x378, 0x379, 0x37b, 0x37c, 0x37e, 0x380, 0x381, 0x383, 0x384, 0x386, 0x388, 0x389, 0x38b, 0x38d, 0x38e, 0x390,
|
||||
|
||||
0x392, 0x393, 0x395, 0x397, 0x398, 0x39a, 0x39c, 0x39d, 0x39f, 0x3a1, 0x3a2, 0x3a4, 0x3a6, 0x3a7, 0x3a9, 0x3ab,
|
||||
0x3ac, 0x3ae, 0x3b0, 0x3b1, 0x3b3, 0x3b5, 0x3b7, 0x3b8, 0x3ba, 0x3bc, 0x3bd, 0x3bf, 0x3c1, 0x3c3, 0x3c4, 0x3c6,
|
||||
|
||||
0x3c8, 0x3ca, 0x3cb, 0x3cd, 0x3cf, 0x3d1, 0x3d2, 0x3d4, 0x3d6, 0x3d8, 0x3da, 0x3db, 0x3dd, 0x3df, 0x3e1, 0x3e3,
|
||||
0x3e4, 0x3e6, 0x3e8, 0x3ea, 0x3ec, 0x3ed, 0x3ef, 0x3f1, 0x3f3, 0x3f5, 0x3f6, 0x3f8, 0x3fa, 0x3fc, 0x3fe, 0x36c
|
||||
};
|
||||
|
||||
/*
|
||||
* Write frequency/octave/keyon data to a channel
|
||||
* [RH] This is totally different from the original MUS library code
|
||||
* but matches exactly what DMX does. I haven't a clue why there are 284
|
||||
* special bytes at the beginning of the table for the first few notes.
|
||||
* That last byte in the table doesn't look right, either, but that's what
|
||||
* it really is.
|
||||
*/
|
||||
void OPLio::OPLwriteFreq(uint channel, uint freq, uint octave, uint keyon)
|
||||
void OPLio::OPLwriteFreq(uint channel, uint note, uint pitch, uint keyon)
|
||||
{
|
||||
int i;
|
||||
int j = (freq<<5) + octave;
|
||||
i = 0;
|
||||
int octave = 0;
|
||||
int j = (note << 5) + pitch;
|
||||
|
||||
if (j < 0)
|
||||
{
|
||||
j = 0;
|
||||
}
|
||||
else if (j >= 0x11C)
|
||||
else if (j >= 284)
|
||||
{
|
||||
j -= 0x11C;
|
||||
i = j / 0x180;
|
||||
if (i > 7)
|
||||
j -= 284;
|
||||
octave = j / (32*12);
|
||||
if (octave > 7)
|
||||
{
|
||||
i = 7;
|
||||
octave = 7;
|
||||
}
|
||||
j = (j % 0x180) + 0x11C;
|
||||
j = (j % (32*12)) + 284;
|
||||
}
|
||||
i = frequencies[j] | (i << 10);
|
||||
int i = frequencies[j] | (octave << 10);
|
||||
|
||||
OPLwriteValue (0xA0, channel, (BYTE)i);
|
||||
OPLwriteValue (0xB0, channel, (BYTE)(i>>8)|(keyon<<5));
|
||||
|
@ -277,20 +298,12 @@ void OPLio::OPLshutup(void)
|
|||
/*
|
||||
* Initialize hardware upon startup
|
||||
*/
|
||||
int OPLio::OPLinit(uint numchips, uint rate)
|
||||
int OPLio::OPLinit(uint numchips)
|
||||
{
|
||||
if (!YM3812Init (numchips, 3579545, rate))
|
||||
if (!YM3812Init (numchips, 3579545, int(OPL_SAMPLE_RATE)))
|
||||
{
|
||||
uint i;
|
||||
|
||||
OPLchannels = OPL2CHANNELS*numchips;
|
||||
for (i = 0; i < numchips; ++i)
|
||||
{
|
||||
OPLwriteReg (i, 0x01, 0x20); // enable Waveform Select
|
||||
OPLwriteReg (i, 0x0B, 0x40); // turn off CSW mode
|
||||
OPLwriteReg (i, 0xBD, 0x00); // set vibrato/tremolo depth to low, set melodic mode
|
||||
}
|
||||
OPLshutup();
|
||||
OPLchannels = OPL2CHANNELS * numchips;
|
||||
OPLwriteInitState();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
@ -299,6 +312,17 @@ int OPLio::OPLinit(uint numchips, uint rate)
|
|||
}
|
||||
}
|
||||
|
||||
void OPLio::OPLwriteInitState()
|
||||
{
|
||||
for (uint i = 0; i < OPLchannels / OPL2CHANNELS; ++i)
|
||||
{
|
||||
OPLwriteReg (i, 0x01, 0x20); // enable Waveform Select
|
||||
OPLwriteReg (i, 0x0B, 0x40); // turn off CSW mode
|
||||
OPLwriteReg (i, 0xBD, 0x00); // set vibrato/tremolo depth to low, set melodic mode
|
||||
}
|
||||
OPLshutup();
|
||||
}
|
||||
|
||||
/*
|
||||
* Deinitialize hardware before shutdown
|
||||
*/
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "doomdef.h"
|
||||
#include "m_swap.h"
|
||||
#include "w_wad.h"
|
||||
#include "fmopl.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -105,7 +106,7 @@ OPLMIDIDevice::~OPLMIDIDevice()
|
|||
|
||||
int OPLMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata)
|
||||
{
|
||||
if (io == NULL || io->OPLinit(TwoChips + 1, uint(OPL_SAMPLE_RATE)))
|
||||
if (io == NULL || io->OPLinit(TwoChips + 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -209,6 +210,7 @@ int OPLMIDIDevice::SetTimeDiv(int timediv)
|
|||
void OPLMIDIDevice::CalcTickRate()
|
||||
{
|
||||
SamplesPerTick = OPL_SAMPLE_RATE / (1000000.0 / Tempo) / Division;
|
||||
io->SetClockRate(SamplesPerTick);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
372
src/oplsynth/music_opldumper_mididevice.cpp
Normal file
372
src/oplsynth/music_opldumper_mididevice.cpp
Normal file
|
@ -0,0 +1,372 @@
|
|||
/*
|
||||
** music_opl_mididevice.cpp
|
||||
** Writes raw OPL commands from the emulated OPL MIDI output to disk.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2008 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include "i_musicinterns.h"
|
||||
#include "templates.h"
|
||||
#include "doomdef.h"
|
||||
#include "m_swap.h"
|
||||
#include "w_wad.h"
|
||||
#include "fmopl.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OPLDumperMIDIDevice Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
OPLDumperMIDIDevice::OPLDumperMIDIDevice(const char *filename)
|
||||
{
|
||||
// Replace the standard OPL device with a disk writer.
|
||||
delete io;
|
||||
io = new DiskWriterIO(filename);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OPLDumperMIDIDevice Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
OPLDumperMIDIDevice::~OPLDumperMIDIDevice()
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OPLDumperMIDIDevice :: Resume
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int OPLDumperMIDIDevice::Resume()
|
||||
{
|
||||
int time;
|
||||
|
||||
time = PlayTick();
|
||||
while (time != 0)
|
||||
{
|
||||
io->WriteDelay(time);
|
||||
time = PlayTick();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OPLDumperMIDIDevice :: Stop
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void OPLDumperMIDIDevice::Stop()
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DiskWriterIO Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DiskWriterIO::DiskWriterIO(const char *filename)
|
||||
: Filename(filename)
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DiskWriterIO Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DiskWriterIO::~DiskWriterIO()
|
||||
{
|
||||
OPLdeinit();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DiskWriterIO :: OPLinit
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int DiskWriterIO::OPLinit(uint numchips)
|
||||
{
|
||||
// If the file extension is unknown or not present, the default format
|
||||
// is RAW. Otherwise, you can use DRO.
|
||||
if (Filename.Len() < 5 || stricmp(&Filename[Filename.Len() - 4], ".dro") != 0)
|
||||
{
|
||||
Format = FMT_RDOS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Format = FMT_DOSBOX;
|
||||
}
|
||||
File = fopen(Filename, "wb");
|
||||
if (File == NULL)
|
||||
{
|
||||
Printf("Could not open %s for writing.\n", Filename.GetChars());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Format == FMT_RDOS)
|
||||
{
|
||||
fwrite("RAWADATA\0", 1, 10, File);
|
||||
NeedClockRate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite("DBRAWOPL"
|
||||
"\0\0" // Minor version number
|
||||
"\1\0" // Major version number
|
||||
"\0\0\0\0" // Total milliseconds
|
||||
"\0\0\0", // Total data
|
||||
1, 20, File);
|
||||
if (numchips == 1)
|
||||
{
|
||||
fwrite("\0\0\0", 1, 4, File); // Single OPL-2
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite("\2\0\0", 1, 4, File); // Dual OPL-2
|
||||
}
|
||||
NeedClockRate = false;
|
||||
}
|
||||
|
||||
TimePerTick = 0;
|
||||
TickMul = 1;
|
||||
CurTime = 0;
|
||||
CurIntTime = 0;
|
||||
CurChip = 0;
|
||||
OPLchannels = OPL2CHANNELS * numchips;
|
||||
OPLwriteInitState();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DiskWriterIO :: OPLdeinit
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DiskWriterIO::OPLdeinit()
|
||||
{
|
||||
if (File != NULL)
|
||||
{
|
||||
if (Format == FMT_RDOS)
|
||||
{
|
||||
WORD endmark = 65535;
|
||||
fwrite(&endmark, 2, 1, File);
|
||||
}
|
||||
else
|
||||
{
|
||||
long where_am_i = ftell(File);
|
||||
DWORD len[2];
|
||||
|
||||
fseek(File, 12, SEEK_SET);
|
||||
len[0] = LittleLong(CurIntTime);
|
||||
len[1] = LittleLong(where_am_i - 24);
|
||||
fwrite(len, 4, 2, File);
|
||||
}
|
||||
fclose(File);
|
||||
File = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DiskWriterIO :: OPLwriteReg
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DiskWriterIO::OPLwriteReg(int which, uint reg, uchar data)
|
||||
{
|
||||
SetChip(which);
|
||||
if (Format == FMT_RDOS)
|
||||
{
|
||||
if (reg != 0 && reg != 2 && (reg != 255 || data != 255))
|
||||
{
|
||||
BYTE cmd[2] = { data, reg };
|
||||
fwrite(cmd, 1, 2, File);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BYTE cmd[3] = { 4, reg, data };
|
||||
fwrite (cmd + (reg > 4), 1, 3 - (reg > 4), File);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DiskWriterIO :: SetChip
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DiskWriterIO :: SetChip(int chipnum)
|
||||
{
|
||||
assert(chipnum == 0 || chipnum == 1);
|
||||
|
||||
if (chipnum != CurChip)
|
||||
{
|
||||
CurChip = chipnum;
|
||||
if (Format == FMT_RDOS)
|
||||
{
|
||||
BYTE switcher[2] = { chipnum + 1, 2 };
|
||||
fwrite(switcher, 1, 2, File);
|
||||
}
|
||||
else
|
||||
{
|
||||
BYTE switcher = chipnum + 2;
|
||||
fwrite(&switcher, 1, 1, File);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DiskWriterIO :: SetClockRate
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DiskWriterIO::SetClockRate(double samples_per_tick)
|
||||
{
|
||||
TimePerTick = samples_per_tick / OPL_SAMPLE_RATE * 1000.0;
|
||||
|
||||
if (Format == FMT_RDOS)
|
||||
{
|
||||
double clock_rate;
|
||||
int clock_mul;
|
||||
WORD clock_word;
|
||||
|
||||
clock_rate = samples_per_tick * ADLIB_CLOCK_MUL;
|
||||
clock_mul = 1;
|
||||
|
||||
// The RDos raw format's clock rate is stored in a word. Therefore,
|
||||
// the longest tick that can be stored is only ~55 ms.
|
||||
while (clock_rate / clock_mul + 0.5 > 65535.0)
|
||||
{
|
||||
clock_mul++;
|
||||
}
|
||||
clock_word = WORD(clock_rate / clock_mul + 0.5);
|
||||
|
||||
if (NeedClockRate)
|
||||
{ // Set the initial clock rate.
|
||||
clock_word = LittleShort(clock_word);
|
||||
fseek(File, 8, SEEK_SET);
|
||||
fwrite(&clock_word, 2, 1, File);
|
||||
fseek(File, 0, SEEK_END);
|
||||
NeedClockRate = false;
|
||||
}
|
||||
else
|
||||
{ // Change the clock rate in the middle of the song.
|
||||
BYTE clock_change[4] = { 0, 2, clock_word & 255, clock_word >> 8 };
|
||||
fwrite(clock_change, 1, 4, File);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DiskWriterIO :: WriteDelay
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DiskWriterIO :: WriteDelay(int ticks)
|
||||
{
|
||||
if (ticks <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Format == FMT_RDOS)
|
||||
{ // RDos raw has very precise delays but isn't very efficient at
|
||||
// storing long delays.
|
||||
BYTE delay[2];
|
||||
|
||||
ticks *= TickMul;
|
||||
delay[1] = 0;
|
||||
while (ticks > 255)
|
||||
{
|
||||
ticks -= 255;
|
||||
delay[0] = 255;
|
||||
fwrite(delay, 1, 2, File);
|
||||
}
|
||||
delay[0] = BYTE(ticks);
|
||||
fwrite(delay, 1, 2, File);
|
||||
}
|
||||
else
|
||||
{ // DosBox only has millisecond-precise delays.
|
||||
int delay;
|
||||
|
||||
CurTime += TimePerTick * ticks;
|
||||
delay = int(CurTime + 0.5) - CurIntTime;
|
||||
CurIntTime += delay;
|
||||
while (delay > 65536)
|
||||
{
|
||||
BYTE cmd[3] = { 1, 255, 255 };
|
||||
fwrite(cmd, 1, 2, File);
|
||||
delay -= 65536;
|
||||
}
|
||||
delay--;
|
||||
if (delay <= 255)
|
||||
{
|
||||
BYTE cmd[2] = { 0, BYTE(delay) };
|
||||
fwrite(cmd, 1, 2, File);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(delay <= 65535);
|
||||
BYTE cmd[3] = { 1, BYTE(delay & 255), BYTE(delay >> 8) };
|
||||
fwrite(cmd, 1, 3, File);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -160,7 +160,7 @@ struct OPLdata {
|
|||
};
|
||||
|
||||
struct OPLio {
|
||||
virtual ~OPLio() {}
|
||||
virtual ~OPLio();
|
||||
|
||||
void OPLwriteChannel(uint regbase, uint channel, uchar data1, uchar data2);
|
||||
void OPLwriteValue(uint regbase, uint channel, uchar value);
|
||||
|
@ -171,14 +171,43 @@ struct OPLio {
|
|||
void OPLwritePan(uint channel, struct OPL2instrument *instr, int pan);
|
||||
void OPLwriteInstrument(uint channel, struct OPL2instrument *instr);
|
||||
void OPLshutup(void);
|
||||
void OPLwriteInitState();
|
||||
|
||||
virtual int OPLinit(uint numchips, uint rate);
|
||||
virtual int OPLinit(uint numchips);
|
||||
virtual void OPLdeinit(void);
|
||||
virtual void OPLwriteReg(int which, uint reg, uchar data);
|
||||
virtual void SetClockRate(double samples_per_tick);
|
||||
virtual void WriteDelay(int ticks);
|
||||
|
||||
uint OPLchannels;
|
||||
};
|
||||
|
||||
struct DiskWriterIO : public OPLio
|
||||
{
|
||||
DiskWriterIO(const char *filename);
|
||||
~DiskWriterIO();
|
||||
|
||||
int OPLinit(uint numchips);
|
||||
void OPLdeinit();
|
||||
void OPLwriteReg(int which, uint reg, uchar data);
|
||||
void SetClockRate(double samples_per_tick);
|
||||
void WriteDelay(int ticks);
|
||||
|
||||
void SetChip(int chipnum);
|
||||
|
||||
FILE *File;
|
||||
FString Filename;
|
||||
int Format;
|
||||
bool NeedClockRate;
|
||||
double TimePerTick; // In milliseconds
|
||||
double CurTime;
|
||||
int CurIntTime;
|
||||
int TickMul;
|
||||
int CurChip;
|
||||
|
||||
enum { FMT_RDOS, FMT_DOSBOX };
|
||||
};
|
||||
|
||||
struct musicBlock {
|
||||
musicBlock();
|
||||
~musicBlock();
|
||||
|
@ -193,8 +222,6 @@ struct musicBlock {
|
|||
|
||||
ulong MLtime;
|
||||
|
||||
int playTick();
|
||||
|
||||
void OPLplayNote(uint channel, uchar note, int volume);
|
||||
void OPLreleaseNote(uint channel, uchar note);
|
||||
void OPLpitchWheel(uint channel, int pitch);
|
||||
|
@ -254,4 +281,7 @@ enum MUSctrl {
|
|||
ctrlResetCtrls
|
||||
};
|
||||
|
||||
#define OPL_SAMPLE_RATE 49716.0
|
||||
#define ADLIB_CLOCK_MUL 24.0
|
||||
|
||||
#endif // __MUSLIB_H_
|
||||
|
|
|
@ -79,7 +79,7 @@ void OPLmusicBlock::ResetChips ()
|
|||
TwoChips = !opl_onechip;
|
||||
Serialize();
|
||||
io->OPLdeinit ();
|
||||
io->OPLinit (TwoChips + 1, uint(OPL_SAMPLE_RATE));
|
||||
io->OPLinit (TwoChips + 1);
|
||||
Unserialize();
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ void OPLmusicBlock::Restart()
|
|||
playingcount = 0;
|
||||
}
|
||||
|
||||
OPLmusicFile::OPLmusicFile (FILE *file, char * musiccache, int len, int maxSamples)
|
||||
OPLmusicFile::OPLmusicFile (FILE *file, char *musiccache, int len)
|
||||
: ScoreLen (len)
|
||||
{
|
||||
if (io == NULL)
|
||||
|
@ -115,29 +115,15 @@ OPLmusicFile::OPLmusicFile (FILE *file, char * musiccache, int len, int maxSampl
|
|||
memcpy(scoredata, &musiccache[0], len);
|
||||
}
|
||||
|
||||
if (io->OPLinit (TwoChips + 1, uint(OPL_SAMPLE_RATE)))
|
||||
if (io->OPLinit (TwoChips + 1))
|
||||
{
|
||||
delete[] scoredata;
|
||||
scoredata = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for MUS format
|
||||
if (*(DWORD *)scoredata == MAKE_ID('M','U','S',0x1a))
|
||||
{
|
||||
FWadLump data = Wads.OpenLumpName ("GENMIDI");
|
||||
if (0 != OPLloadBank (data))
|
||||
{
|
||||
delete[] scoredata;
|
||||
scoredata = NULL;
|
||||
return;
|
||||
}
|
||||
BlockForStats = this;
|
||||
SamplesPerTick = OPL_SAMPLE_RATE / 140.0;
|
||||
RawPlayer = NotRaw;
|
||||
}
|
||||
// Check for RDosPlay raw OPL format
|
||||
else if (((DWORD *)scoredata)[0] == MAKE_ID('R','A','W','A') &&
|
||||
if (((DWORD *)scoredata)[0] == MAKE_ID('R','A','W','A') &&
|
||||
((DWORD *)scoredata)[1] == MAKE_ID('D','A','T','A'))
|
||||
{
|
||||
RawPlayer = RDosPlay;
|
||||
|
@ -145,7 +131,16 @@ OPLmusicFile::OPLmusicFile (FILE *file, char * musiccache, int len, int maxSampl
|
|||
{ // A clock speed of 0 is bad
|
||||
*(WORD *)(scoredata + 8) = 0xFFFF;
|
||||
}
|
||||
SamplesPerTick = OPL_SAMPLE_RATE * LittleShort(*(WORD *)(scoredata + 8)) / 1193180.0;
|
||||
SamplesPerTick = LittleShort(*(WORD *)(scoredata + 8)) / ADLIB_CLOCK_MUL;
|
||||
}
|
||||
// Check for DosBox OPL dump
|
||||
else if (((DWORD *)scoredata)[0] == MAKE_ID('D','B','R','A') &&
|
||||
((DWORD *)scoredata)[1] == MAKE_ID('W','O','P','L') &&
|
||||
((DWORD *)scoredata)[2] == MAKE_ID(0,0,1,0))
|
||||
{
|
||||
RawPlayer = DosBox;
|
||||
SamplesPerTick = OPL_SAMPLE_RATE / 1000;
|
||||
ScoreLen = MIN<int>(len - 24, LittleLong(((DWORD *)scoredata)[4]));
|
||||
}
|
||||
// Check for modified IMF format (includes a header)
|
||||
else if (((DWORD *)scoredata)[0] == MAKE_ID('A','D','L','I') &&
|
||||
|
@ -202,14 +197,16 @@ void OPLmusicFile::SetLooping (bool loop)
|
|||
void OPLmusicFile::Restart ()
|
||||
{
|
||||
OPLmusicBlock::Restart();
|
||||
if (RawPlayer == NotRaw)
|
||||
{
|
||||
score = scoredata + ((MUSheader *)scoredata)->scoreStart;
|
||||
}
|
||||
else if (RawPlayer == RDosPlay)
|
||||
WhichChip = 0;
|
||||
if (RawPlayer == RDosPlay)
|
||||
{
|
||||
score = scoredata + 10;
|
||||
SamplesPerTick = OPL_SAMPLE_RATE * LittleShort(*(WORD *)(scoredata + 8)) / 1193180.0;
|
||||
SamplesPerTick = LittleShort(*(WORD *)(scoredata + 8)) / ADLIB_CLOCK_MUL;
|
||||
}
|
||||
else if (RawPlayer == DosBox)
|
||||
{
|
||||
score = scoredata + 24;
|
||||
SamplesPerTick = OPL_SAMPLE_RATE / 1000;
|
||||
}
|
||||
else if (RawPlayer == IMF)
|
||||
{
|
||||
|
@ -226,6 +223,7 @@ void OPLmusicFile::Restart ()
|
|||
score += 4; // Skip song length
|
||||
}
|
||||
}
|
||||
io->SetClockRate(SamplesPerTick);
|
||||
}
|
||||
|
||||
bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
|
||||
|
@ -289,6 +287,7 @@ bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
|
|||
else
|
||||
{
|
||||
prevEnded = false;
|
||||
io->WriteDelay(next);
|
||||
NextTickIn += SamplesPerTick * next;
|
||||
assert (NextTickIn >= 0);
|
||||
MLtime += next;
|
||||
|
@ -303,11 +302,7 @@ int OPLmusicFile::PlayTick ()
|
|||
{
|
||||
BYTE reg, data;
|
||||
|
||||
if (RawPlayer == NotRaw)
|
||||
{
|
||||
return playTick ();
|
||||
}
|
||||
else if (RawPlayer == RDosPlay)
|
||||
if (RawPlayer == RDosPlay)
|
||||
{
|
||||
while (score < scoredata + ScoreLen)
|
||||
{
|
||||
|
@ -325,9 +320,18 @@ int OPLmusicFile::PlayTick ()
|
|||
case 2: // Speed change or OPL3 switch
|
||||
if (data == 0)
|
||||
{
|
||||
SamplesPerTick = OPL_SAMPLE_RATE * LittleShort(*(WORD *)(score)) / 1193180.0;
|
||||
SamplesPerTick = LittleShort(*(WORD *)(score)) / ADLIB_CLOCK_MUL;
|
||||
io->SetClockRate(SamplesPerTick);
|
||||
score += 2;
|
||||
}
|
||||
else if (data == 1)
|
||||
{
|
||||
WhichChip = 0;
|
||||
}
|
||||
else if (data == 2)
|
||||
{
|
||||
WhichChip = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF: // End of song
|
||||
|
@ -338,11 +342,55 @@ int OPLmusicFile::PlayTick ()
|
|||
break;
|
||||
|
||||
default: // It's something to stuff into the OPL chip
|
||||
io->OPLwriteReg (0, reg, data);
|
||||
if (WhichChip == 0 || TwoChips)
|
||||
{
|
||||
io->OPLwriteReg(WhichChip, reg, data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (RawPlayer == DosBox)
|
||||
{
|
||||
while (score < scoredata + ScoreLen)
|
||||
{
|
||||
reg = *score++;
|
||||
|
||||
if (reg == 4)
|
||||
{
|
||||
reg = *score++;
|
||||
data = *score++;
|
||||
}
|
||||
else if (reg == 0)
|
||||
{ // One-byte delay
|
||||
return *score++ + 1;
|
||||
}
|
||||
else if (reg == 1)
|
||||
{ // Two-byte delay
|
||||
int delay = score[0] + (score[1] << 8) + 1;
|
||||
score += 2;
|
||||
return delay;
|
||||
}
|
||||
else if (reg == 2)
|
||||
{ // Select OPL chip 0
|
||||
WhichChip = 0;
|
||||
continue;
|
||||
}
|
||||
else if (reg == 3)
|
||||
{ // Select OPL chip 1
|
||||
WhichChip = 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = *score++;
|
||||
}
|
||||
if (WhichChip == 0 || TwoChips)
|
||||
{
|
||||
io->OPLwriteReg(WhichChip, reg, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (RawPlayer == IMF)
|
||||
{
|
||||
WORD delay = 0;
|
||||
|
@ -398,161 +446,33 @@ ADD_STAT (opl)
|
|||
}
|
||||
}
|
||||
|
||||
struct DiskWriterIO : public OPLio
|
||||
OPLmusicFile::OPLmusicFile(const OPLmusicFile *source, const char *filename)
|
||||
{
|
||||
DiskWriterIO () : File(NULL) {}
|
||||
virtual ~DiskWriterIO () { if (File != NULL) fclose (File); }
|
||||
int OPLinit(const char *filename);
|
||||
virtual void OPLwriteReg(int which, uint reg, uchar data);
|
||||
|
||||
FILE *File;
|
||||
bool RawFormat;
|
||||
};
|
||||
|
||||
class OPLmusicWriter : public musicBlock
|
||||
{
|
||||
public:
|
||||
OPLmusicWriter (const char *songname, const char *filename);
|
||||
~OPLmusicWriter ();
|
||||
void Go ();
|
||||
|
||||
bool SharingData;
|
||||
FILE *File;
|
||||
};
|
||||
|
||||
OPLmusicWriter::OPLmusicWriter (const char *songname, const char *filename)
|
||||
{
|
||||
io = NULL;
|
||||
SharingData = true;
|
||||
if (songname == NULL)
|
||||
ScoreLen = source->ScoreLen;
|
||||
scoredata = new BYTE[ScoreLen];
|
||||
memcpy(scoredata, source->scoredata, ScoreLen);
|
||||
SamplesPerTick = source->SamplesPerTick;
|
||||
RawPlayer = source->RawPlayer;
|
||||
score = source->score;
|
||||
TwoChips = source->TwoChips;
|
||||
WhichChip = 0;
|
||||
if (io != NULL)
|
||||
{
|
||||
if (BlockForStats == NULL)
|
||||
{
|
||||
Printf ("Not currently playing an OPL song.\n");
|
||||
return;
|
||||
}
|
||||
scoredata = BlockForStats->scoredata;
|
||||
OPLinstruments = BlockForStats->OPLinstruments;
|
||||
}
|
||||
else
|
||||
{
|
||||
SharingData = false;
|
||||
int lumpnum = Wads.CheckNumForName (songname, ns_music);
|
||||
if (lumpnum == -1)
|
||||
{
|
||||
Printf ("Song %s is unknown.\n", songname);
|
||||
return;
|
||||
}
|
||||
FWadLump song = Wads.OpenLumpNum (lumpnum);
|
||||
scoredata = new BYTE [song.GetLength ()];
|
||||
song.Read (scoredata, song.GetLength());
|
||||
FWadLump genmidi = Wads.OpenLumpName ("GENMIDI");
|
||||
OPLloadBank (genmidi);
|
||||
}
|
||||
io = new DiskWriterIO ();
|
||||
if (((DiskWriterIO *)io)->OPLinit (filename) == 0)
|
||||
{
|
||||
OPLplayMusic (127);
|
||||
score = scoredata + ((MUSheader *)scoredata)->scoreStart;
|
||||
Go ();
|
||||
delete io;
|
||||
}
|
||||
io = new DiskWriterIO(filename);
|
||||
io->OPLinit(TwoChips);
|
||||
Restart();
|
||||
}
|
||||
|
||||
OPLmusicWriter::~OPLmusicWriter ()
|
||||
void OPLmusicFile::Dump()
|
||||
{
|
||||
if (io != NULL) delete io;
|
||||
if (!SharingData)
|
||||
int time;
|
||||
|
||||
time = PlayTick();
|
||||
while (time != 0)
|
||||
{
|
||||
delete scoredata;
|
||||
}
|
||||
else
|
||||
{
|
||||
OPLinstruments = NULL;
|
||||
io->WriteDelay(time);
|
||||
time = PlayTick();
|
||||
}
|
||||
}
|
||||
|
||||
void OPLmusicWriter::Go ()
|
||||
{
|
||||
int next;
|
||||
|
||||
while ((next = playTick()) != 0)
|
||||
{
|
||||
MLtime += next;
|
||||
while (next > 255)
|
||||
{
|
||||
io->OPLwriteReg (10, 0, 255);
|
||||
next -= 255;
|
||||
}
|
||||
io->OPLwriteReg (10, 0, next);
|
||||
}
|
||||
io->OPLwriteReg (10, 0xFF, 0xFF);
|
||||
}
|
||||
|
||||
int DiskWriterIO::OPLinit (const char *filename)
|
||||
{
|
||||
int numchips;
|
||||
//size_t namelen;
|
||||
|
||||
// If the file extension is unknown or not present, the default format
|
||||
// is RAW. Otherwise, you can use DRO. But not right now. The DRO format
|
||||
// is still in a state of flux, so I don't want the hassle.
|
||||
//namelen = strlen (filename);
|
||||
RawFormat = 1; //(namelen < 5 || stricmp (filename + namelen - 4, ".dro") != 0);
|
||||
File = fopen (filename, "wb");
|
||||
if (File == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (RawFormat)
|
||||
{
|
||||
fwrite ("RAWADATA", 1, 8, File);
|
||||
WORD clock = LittleShort(17045/2);
|
||||
fwrite (&clock, 2, 1, File);
|
||||
numchips = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
numchips = 2;
|
||||
}
|
||||
|
||||
OPLchannels = OPL2CHANNELS*numchips;
|
||||
for (int i = 0; i < numchips; ++i)
|
||||
{
|
||||
OPLwriteReg (i, 0x01, 0x20); // enable Waveform Select
|
||||
OPLwriteReg (i, 0x0B, 0x40); // turn off CSW mode
|
||||
OPLwriteReg (i, 0xBD, 0x00); // set vibrato/tremolo depth to low, set melodic mode
|
||||
}
|
||||
OPLshutup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DiskWriterIO::OPLwriteReg(int which, uint reg, uchar data)
|
||||
{
|
||||
if (which == 10 || (reg != 0 && reg != 2 && reg != 0xFF))
|
||||
{
|
||||
struct { BYTE data, reg; } out = { data, reg };
|
||||
fwrite (&out, 2, 1, File);
|
||||
}
|
||||
else
|
||||
{
|
||||
reg = reg;
|
||||
}
|
||||
}
|
||||
|
||||
CCMD (writeopl)
|
||||
{
|
||||
if (argv.argc() == 2)
|
||||
{
|
||||
OPLmusicWriter writer (NULL, argv[1]);
|
||||
}
|
||||
else if (argv.argc() == 3)
|
||||
{
|
||||
OPLmusicWriter writer (argv[1], argv[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("Usage: writeopl [songname] <filename>");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,13 +9,11 @@
|
|||
#include "muslib.h"
|
||||
#include "files.h"
|
||||
|
||||
#define OPL_SAMPLE_RATE 49716.0
|
||||
|
||||
class OPLmusicBlock : public musicBlock
|
||||
{
|
||||
public:
|
||||
OPLmusicBlock();
|
||||
~OPLmusicBlock();
|
||||
virtual ~OPLmusicBlock();
|
||||
|
||||
bool ServiceStream(void *buff, int numbytes);
|
||||
void ResetChips();
|
||||
|
@ -43,16 +41,20 @@ protected:
|
|||
class OPLmusicFile : public OPLmusicBlock
|
||||
{
|
||||
public:
|
||||
OPLmusicFile(FILE *file, char *musiccache, int len, int maxSamples);
|
||||
~OPLmusicFile();
|
||||
OPLmusicFile(FILE *file, char *musiccache, int len);
|
||||
OPLmusicFile(const OPLmusicFile *source, const char *filename);
|
||||
virtual ~OPLmusicFile();
|
||||
|
||||
bool IsValid() const;
|
||||
void SetLooping(bool loop);
|
||||
void Restart();
|
||||
void Dump();
|
||||
|
||||
protected:
|
||||
OPLmusicFile() {}
|
||||
int PlayTick();
|
||||
|
||||
enum { NotRaw, RDosPlay, IMF } RawPlayer;
|
||||
enum { RDosPlay, IMF, DosBox } RawPlayer;
|
||||
int ScoreLen;
|
||||
int WhichChip;
|
||||
};
|
||||
|
|
|
@ -556,7 +556,7 @@ void FBehavior::StaticLoadDefaultModules ()
|
|||
|
||||
while ((lump = Wads.FindLump ("LOADACS", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump, "LOADACS");
|
||||
FScanner sc(lump);
|
||||
while (sc.GetString())
|
||||
{
|
||||
int acslump = Wads.CheckNumForName (sc.String, ns_acslibrary);
|
||||
|
|
|
@ -228,7 +228,7 @@ void P_RunEffect (AActor *actor, int effects)
|
|||
particle_t *particle;
|
||||
int i;
|
||||
|
||||
if ((effects & FX_ROCKET) && cl_rockettrails)
|
||||
if ((effects & FX_ROCKET) && (cl_rockettrails & 1))
|
||||
{
|
||||
// Rocket trail
|
||||
|
||||
|
@ -274,7 +274,7 @@ void P_RunEffect (AActor *actor, int effects)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if ((effects & FX_GRENADE) && (cl_rockettrails))
|
||||
if ((effects & FX_GRENADE) && (cl_rockettrails & 1))
|
||||
{
|
||||
// Grenade trail
|
||||
|
||||
|
|
|
@ -1884,7 +1884,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
|
|||
}
|
||||
else
|
||||
{
|
||||
actor->SetState (actor->SpawnState);
|
||||
actor->SetIdle();
|
||||
actor->flags &= ~MF_INCHASE;
|
||||
return;
|
||||
}
|
||||
|
@ -1945,7 +1945,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
|
|||
if (newgoal != NULL && delay != 0)
|
||||
{
|
||||
actor->flags4 |= MF4_INCOMBAT;
|
||||
actor->SetState (actor->SpawnState);
|
||||
actor->SetIdle();
|
||||
}
|
||||
actor->flags &= ~MF_INCHASE;
|
||||
actor->goal = newgoal;
|
||||
|
|
|
@ -90,13 +90,20 @@ void P_UnPredictPlayer ();
|
|||
extern fixed_t FloatBobOffsets[64];
|
||||
extern AActor *MissileActor;
|
||||
|
||||
void P_SpawnPlayer (mapthing2_t* mthing, bool tempplayer=false);
|
||||
APlayerPawn *P_SpawnPlayer (mapthing2_t* mthing, bool tempplayer=false);
|
||||
|
||||
void P_ThrustMobj (AActor *mo, angle_t angle, fixed_t move);
|
||||
int P_FaceMobj (AActor *source, AActor *target, angle_t *delta);
|
||||
bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax);
|
||||
|
||||
AActor *P_SpawnPuff (const PClass *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, bool hit=false, bool temporary=false);
|
||||
enum EPuffFlags
|
||||
{
|
||||
PF_HITTHING = 1,
|
||||
PF_MELEERANGE = 2,
|
||||
PF_TEMPORARY = 4
|
||||
};
|
||||
|
||||
AActor *P_SpawnPuff (const PClass *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, int flags = 0);
|
||||
void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AActor *originator);
|
||||
void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator);
|
||||
void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator);
|
||||
|
@ -307,8 +314,8 @@ bool P_ChangeSector (sector_t* sector, int crunch, int amt, int floorOrCeil, boo
|
|||
extern AActor* linetarget; // who got hit (or NULL)
|
||||
|
||||
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, fixed_t vrange=0, bool forcenosmart=false);
|
||||
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype);
|
||||
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype);
|
||||
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, bool ismelee = false);
|
||||
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, bool ismelee = false);
|
||||
void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch);
|
||||
void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch);
|
||||
void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version
|
||||
|
|
|
@ -3070,7 +3070,7 @@ static bool CheckForSpectral (FTraceResults &res)
|
|||
}
|
||||
|
||||
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
||||
int pitch, int damage, FName damageType, const PClass *pufftype)
|
||||
int pitch, int damage, FName damageType, const PClass *pufftype, bool ismeleeattack)
|
||||
{
|
||||
fixed_t vx, vy, vz, shootz;
|
||||
FTraceResults trace;
|
||||
|
@ -3079,6 +3079,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
|||
bool hitGhosts;
|
||||
bool killPuff = false;
|
||||
AActor *puff = NULL;
|
||||
int flags = ismeleeattack? PF_MELEERANGE : 0;
|
||||
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
pitch = (angle_t)(pitch) >> ANGLETOFINESHIFT;
|
||||
|
@ -3114,7 +3115,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
|||
}
|
||||
if (puffDefaults->flags3 & MF3_ALWAYSPUFF)
|
||||
{ // Spawn the puff anyway
|
||||
puff = P_SpawnPuff (pufftype, trace.X, trace.Y, trace.Z, angle - ANG180, 2);
|
||||
puff = P_SpawnPuff (pufftype, trace.X, trace.Y, trace.Z, angle - ANG180, 2, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3133,7 +3134,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
|||
fixed_t closer = trace.Distance - 4*FRACUNIT;
|
||||
puff = P_SpawnPuff (pufftype, t1->x + FixedMul (vx, closer),
|
||||
t1->y + FixedMul (vy, closer),
|
||||
shootz + FixedMul (vz, closer), angle - ANG90, 0);
|
||||
shootz + FixedMul (vz, closer), angle - ANG90, 0, flags);
|
||||
}
|
||||
|
||||
// [RH] Spawn a decal
|
||||
|
@ -3186,7 +3187,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
|||
(trace.Actor->flags & MF_NOBLOOD) ||
|
||||
(trace.Actor->flags2 & (MF2_INVULNERABLE|MF2_DORMANT)))
|
||||
{
|
||||
puff = P_SpawnPuff (pufftype, hitx, hity, hitz, angle - ANG180, 2, true);
|
||||
puff = P_SpawnPuff (pufftype, hitx, hity, hitz, angle - ANG180, 2, flags|PF_HITTHING);
|
||||
}
|
||||
if (!(GetDefaultByType(pufftype)->flags3&MF3_BLOODLESSIMPACT))
|
||||
{
|
||||
|
@ -3233,7 +3234,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
|||
{
|
||||
// Since the puff is the damage inflictor we need it here
|
||||
// regardless of whether it is displayed or not.
|
||||
puff = P_SpawnPuff (pufftype, hitx, hity, hitz, angle - ANG180, 2, true, true);
|
||||
puff = P_SpawnPuff (pufftype, hitx, hity, hitz, angle - ANG180, 2, flags|PF_HITTHING|PF_TEMPORARY);
|
||||
killPuff = true;
|
||||
}
|
||||
P_DamageMobj (trace.Actor, puff ? puff : t1, t1, damage, damageType, flags);
|
||||
|
@ -3244,7 +3245,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
|||
|
||||
if (puff == NULL)
|
||||
{ // Spawn puff just to get a mass for the splash
|
||||
puff = P_SpawnPuff (pufftype, hitx, hity, hitz, angle - ANG180, 2, true, true);
|
||||
puff = P_SpawnPuff (pufftype, hitx, hity, hitz, angle - ANG180, 2, flags|PF_HITTHING|PF_TEMPORARY);
|
||||
killPuff = true;
|
||||
}
|
||||
SpawnDeepSplash (t1, trace, puff, vx, vy, vz);
|
||||
|
@ -3259,7 +3260,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
|||
}
|
||||
|
||||
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
||||
int pitch, int damage, FName damageType, FName pufftype)
|
||||
int pitch, int damage, FName damageType, FName pufftype, bool ismeleeattack)
|
||||
{
|
||||
const PClass * type = PClass::FindClass(pufftype);
|
||||
if (type == NULL)
|
||||
|
@ -3268,7 +3269,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
|||
}
|
||||
else
|
||||
{
|
||||
return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type);
|
||||
return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, ismeleeattack);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3535,7 +3536,7 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color
|
|||
if ((RailHits[i].HitActor->flags & MF_NOBLOOD) ||
|
||||
(RailHits[i].HitActor->flags2 & (MF2_DORMANT|MF2_INVULNERABLE)))
|
||||
{
|
||||
if (puffclass != NULL) P_SpawnPuff (puffclass, x, y, z, source->angle - ANG180, 1, true);
|
||||
if (puffclass != NULL) P_SpawnPuff (puffclass, x, y, z, source->angle - ANG180, 1, PF_HITTHING);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
176
src/p_mobj.cpp
176
src/p_mobj.cpp
|
@ -81,9 +81,8 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj);
|
|||
extern cycle_t BotSupportCycles;
|
||||
extern cycle_t BotWTG;
|
||||
extern fixed_t attackrange;
|
||||
extern int tmfloorpic;
|
||||
extern sector_t *tmfloorsector;
|
||||
EXTERN_CVAR (Bool, r_drawfuzz);
|
||||
EXTERN_CVAR (Int, cl_rockettrails)
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
|
@ -108,7 +107,6 @@ static FRandom pr_missiledamage ("MissileDamage");
|
|||
static FRandom pr_multiclasschoice ("MultiClassChoice");
|
||||
static FRandom pr_rockettrail("RocketTrail");
|
||||
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
FRandom pr_spawnmobj ("SpawnActor");
|
||||
|
@ -327,7 +325,8 @@ void AActor::Serialize (FArchive &arc)
|
|||
<< DamageType
|
||||
<< gravity
|
||||
<< FastChaseStrafeCount
|
||||
<< master;
|
||||
<< master
|
||||
<< smokecounter;
|
||||
|
||||
if (arc.IsStoring ())
|
||||
{
|
||||
|
@ -1461,11 +1460,12 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
mo->momx = mo->momy = mo->momz = 0;
|
||||
if (!(mo->flags2 & MF2_DORMANT))
|
||||
{
|
||||
mo->SetState (mo->SeeState != NULL ? mo->SeeState : mo->SpawnState);
|
||||
if (mo->SeeState != NULL) mo->SetState (mo->SeeState);
|
||||
else mo->SetIdle();
|
||||
}
|
||||
else
|
||||
{
|
||||
mo->SetState (mo->SpawnState);
|
||||
mo->SetIdle();
|
||||
mo->tics = -1;
|
||||
}
|
||||
}
|
||||
|
@ -2462,11 +2462,12 @@ bool AActor::Slam (AActor *thing)
|
|||
int dam = GetMissileDamage (7, 1);
|
||||
P_DamageMobj (thing, this, this, dam, NAME_Melee);
|
||||
P_TraceBleed (dam, thing, this);
|
||||
SetState (SeeState != NULL ? SeeState : SpawnState);
|
||||
if (SeeState != NULL) SetState (SeeState);
|
||||
else SetIdle();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetState (SpawnState);
|
||||
SetIdle();
|
||||
tics = -1;
|
||||
}
|
||||
}
|
||||
|
@ -2572,25 +2573,8 @@ void AActor::SetShade (int r, int g, int b)
|
|||
//
|
||||
// P_MobjThinker
|
||||
//
|
||||
|
||||
CVAR(Bool, sv_rocketsmoke, false, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
||||
|
||||
void AActor::Tick ()
|
||||
{
|
||||
if (effects&FX_ROCKET && sv_rocketsmoke && ++visdir==4)
|
||||
{
|
||||
// add some smoke behind the rocket
|
||||
visdir=0;
|
||||
AActor * th = Spawn("RocketSmokeTrail", x-momx, y-momy, z, ALLOW_REPLACE);
|
||||
if (th)
|
||||
{
|
||||
th->momz = FRACUNIT;
|
||||
th->tics -= pr_rockettrail()&3;
|
||||
if (th->tics < 1) th->tics = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// [RH] Data for Heretic/Hexen scrolling sectors
|
||||
static const BYTE HexenScrollDirs[8] = { 64, 0, 192, 128, 96, 32, 224, 160 };
|
||||
static const BYTE HexenSpeedMuls[3] = { 5, 10, 25 };
|
||||
|
@ -2623,6 +2607,19 @@ void AActor::Tick ()
|
|||
PrevY = y;
|
||||
PrevZ = z;
|
||||
|
||||
if (flags5 & MF5_NOINTERACTION)
|
||||
{
|
||||
// only do the minimally necessary things here to save time.
|
||||
UnlinkFromWorld ();
|
||||
flags |= MF_NOBLOCKMAP;
|
||||
x += momx;
|
||||
y += momy;
|
||||
z += momz;
|
||||
LinkToWorld ();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
AInventory * item = Inventory;
|
||||
|
||||
// Handle powerup effects here so that the order is controlled
|
||||
|
@ -2650,12 +2647,46 @@ void AActor::Tick ()
|
|||
return;
|
||||
}
|
||||
|
||||
if (cl_rockettrails & 2)
|
||||
{
|
||||
if (effects & FX_ROCKET)
|
||||
{
|
||||
if (++smokecounter==4)
|
||||
{
|
||||
// add some smoke behind the rocket
|
||||
smokecounter = 0;
|
||||
AActor * th = Spawn("RocketSmokeTrail", x-momx, y-momy, z-momz, ALLOW_REPLACE);
|
||||
if (th)
|
||||
{
|
||||
th->tics -= pr_rockettrail()&3;
|
||||
if (th->tics < 1) th->tics = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (effects & FX_GRENADE)
|
||||
{
|
||||
if (++smokecounter==8)
|
||||
{
|
||||
smokecounter = 0;
|
||||
angle_t moveangle = R_PointToAngle2(0,0,momx,momy);
|
||||
AActor * th = Spawn("GrenadeSmokeTrail",
|
||||
x - FixedMul (finecosine[(moveangle)>>ANGLETOFINESHIFT], radius*2) + (pr_rockettrail()<<10),
|
||||
y - FixedMul (finesine[(moveangle)>>ANGLETOFINESHIFT], radius*2) + (pr_rockettrail()<<10),
|
||||
z - (height>>3) * (momz>>16) + (2*height)/3, ALLOW_REPLACE);
|
||||
if (th)
|
||||
{
|
||||
th->tics -= pr_rockettrail()&3;
|
||||
if (th->tics < 1) th->tics = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixed_t oldz = z;
|
||||
|
||||
// [RH] Give the pain elemental vertical friction
|
||||
// This used to be in APainElemental::Tick but in order to use
|
||||
// A_PainAttack with other monsters it has to be here!
|
||||
// A_PainAttack with other monsters it has to be here
|
||||
if (flags4 & MF4_VFRICTION)
|
||||
{
|
||||
if (health >0)
|
||||
|
@ -3039,6 +3070,7 @@ void AActor::Tick ()
|
|||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// cycle through states, calling action functions at transitions
|
||||
if (tics != -1)
|
||||
|
@ -3326,7 +3358,7 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t
|
|||
actor->ceilingsector = actor->Sector;
|
||||
actor->ceilingpic = actor->ceilingsector->ceilingpic;
|
||||
}
|
||||
else
|
||||
else if (!(actor->flags5 & MF5_NOINTERACTION))
|
||||
{
|
||||
P_FindFloorCeiling (actor);
|
||||
actor->floorz = tmffloorz;
|
||||
|
@ -3337,6 +3369,16 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t
|
|||
actor->ceilingpic = tmfceilingpic;
|
||||
actor->ceilingsector = tmfceilingsector;
|
||||
}
|
||||
else
|
||||
{
|
||||
actor->floorz = FIXED_MIN;
|
||||
actor->dropoffz = FIXED_MIN;
|
||||
actor->ceilingz = FIXED_MAX;
|
||||
actor->floorpic = 0;
|
||||
actor->floorsector = actor->Sector;
|
||||
actor->ceilingpic = 0;
|
||||
actor->ceilingsector = actor->Sector;
|
||||
}
|
||||
|
||||
actor->SpawnPoint[0] = ix >> FRACBITS;
|
||||
actor->SpawnPoint[1] = iy >> FRACBITS;
|
||||
|
@ -3599,7 +3641,7 @@ EXTERN_CVAR (Bool, chasedemo)
|
|||
|
||||
extern bool demonew;
|
||||
|
||||
void P_SpawnPlayer (mapthing2_t *mthing, bool tempplayer)
|
||||
APlayerPawn *P_SpawnPlayer (mapthing2_t *mthing, bool tempplayer)
|
||||
{
|
||||
int playernum;
|
||||
player_t *p;
|
||||
|
@ -3626,7 +3668,7 @@ void P_SpawnPlayer (mapthing2_t *mthing, bool tempplayer)
|
|||
|
||||
// not playing?
|
||||
if (playernum >= MAXPLAYERS || !playeringame[playernum])
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
p = &players[playernum];
|
||||
|
||||
|
@ -3823,6 +3865,7 @@ void P_SpawnPlayer (mapthing2_t *mthing, bool tempplayer)
|
|||
FBehavior::StaticStartTypedScripts (SCRIPT_Respawn, p->mo, true);
|
||||
}
|
||||
}
|
||||
return mobj;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3832,23 +3875,21 @@ void P_SpawnPlayer (mapthing2_t *mthing, bool tempplayer)
|
|||
// already be in host byte order.
|
||||
//
|
||||
// [RH] position is used to weed out unwanted start spots
|
||||
void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
||||
AActor *P_SpawnMapThing (mapthing2_t *mthing, int position)
|
||||
{
|
||||
const PClass *i;
|
||||
int mask;
|
||||
AActor *mobj;
|
||||
fixed_t x, y, z;
|
||||
|
||||
T_PrepareSpawnThing();
|
||||
|
||||
if (mthing->type == 0 || mthing->type == -1)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
// count deathmatch start positions
|
||||
if (mthing->type == 11)
|
||||
{
|
||||
deathmatchstarts.Push (*mthing);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Convert Strife starts to Hexen-style starts
|
||||
|
@ -3889,7 +3930,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
polyspawns = polyspawn;
|
||||
if (mthing->type != PO_ANCHOR_TYPE)
|
||||
po_NumPolyobjs++;
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check for players specially
|
||||
|
@ -3927,13 +3968,13 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
}
|
||||
if (!(mthing->flags & mask))
|
||||
{
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mask = G_SkillProperty(SKILLP_SpawnFilter);
|
||||
if (!(mthing->flags & mask))
|
||||
{
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check class spawn masks. Now with player classes available
|
||||
|
@ -3943,7 +3984,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
int spawnmask = players[consoleplayer].GetSpawnClass();
|
||||
if (spawnmask != 0 && (mthing->flags & spawnmask) == 0)
|
||||
{ // Not for current class
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (!deathmatch)
|
||||
|
@ -3962,7 +4003,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
}
|
||||
if (mask != -1 && (mthing->flags & mask) == 0)
|
||||
{
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3971,14 +4012,14 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
{
|
||||
// [RH] Only spawn spots that match position.
|
||||
if (mthing->args[0] != position)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
// save spots for respawning in network games
|
||||
playerstarts[pnum] = *mthing;
|
||||
if (!deathmatch)
|
||||
P_SpawnPlayer (mthing);
|
||||
return P_SpawnPlayer (mthing);
|
||||
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// [RH] sound sequence overriders
|
||||
|
@ -3986,7 +4027,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
{
|
||||
P_PointInSector (mthing->x<<FRACBITS,
|
||||
mthing->y<<FRACBITS)->seqType = mthing->type - 1400;
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
else if (mthing->type == 1411)
|
||||
{
|
||||
|
@ -4006,7 +4047,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
P_PointInSector (mthing->x << FRACBITS,
|
||||
mthing->y << FRACBITS)->seqType = type;
|
||||
}
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// [RH] Determine if it is an old ambient thing, and if so,
|
||||
|
@ -4053,7 +4094,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
|
||||
// don't spawn keycards and players in deathmatch
|
||||
if (deathmatch && info->flags & MF_NOTDMATCH)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
// [RH] don't spawn extra weapons in coop if so desired
|
||||
if (multiplayer && !deathmatch && (dmflags & DF_NO_COOP_WEAPON_SPAWN))
|
||||
|
@ -4061,14 +4102,14 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
if (i->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
|
||||
{
|
||||
if ((mthing->flags & (MTF_DEATHMATCH|MTF_SINGLE)) == MTF_DEATHMATCH)
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// don't spawn any monsters if -nomonsters
|
||||
if (((level.flags & LEVEL_NOMONSTERS) || (dmflags & DF_NO_MONSTERS)) && info->flags3 & MF3_ISMONSTER )
|
||||
{
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// [RH] Other things that shouldn't be spawned depending on dmflags
|
||||
|
@ -4077,13 +4118,11 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
if (dmflags & DF_NO_HEALTH)
|
||||
{
|
||||
if (i->IsDescendantOf (RUNTIME_CLASS(AHealth)))
|
||||
return;
|
||||
return NULL;
|
||||
if (i->TypeName == NAME_Berserk)
|
||||
return;
|
||||
if (i->TypeName == NAME_Soulsphere)
|
||||
return;
|
||||
return NULL;
|
||||
if (i->TypeName == NAME_Megasphere)
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
if (dmflags & DF_NO_ITEMS)
|
||||
{
|
||||
|
@ -4093,9 +4132,9 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
if (dmflags & DF_NO_ARMOR)
|
||||
{
|
||||
if (i->IsDescendantOf (RUNTIME_CLASS(AArmor)))
|
||||
return;
|
||||
return NULL;
|
||||
if (i->TypeName == NAME_Megasphere)
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4138,13 +4177,11 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
|
||||
mobj->angle = (DWORD)((mthing->angle * UCONST64(0x100000000)) / 360);
|
||||
mobj->BeginPlay ();
|
||||
if (mobj->ObjectFlags & OF_EuthanizeMe)
|
||||
if (!(mobj->ObjectFlags & OF_EuthanizeMe))
|
||||
{
|
||||
return;
|
||||
}
|
||||
mobj->LevelSpawned ();
|
||||
|
||||
T_RegisterSpawnThing(mobj);
|
||||
}
|
||||
return mobj;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4158,7 +4195,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
|
|||
// P_SpawnPuff
|
||||
//
|
||||
|
||||
AActor *P_SpawnPuff (const PClass *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, bool hitthing, bool temporary)
|
||||
AActor *P_SpawnPuff (const PClass *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, int flags)
|
||||
{
|
||||
AActor *puff;
|
||||
|
||||
|
@ -4170,26 +4207,26 @@ AActor *P_SpawnPuff (const PClass *pufftype, fixed_t x, fixed_t y, fixed_t z, an
|
|||
// it will enter the crash state. This is used by the StrifeSpark
|
||||
// and BlasterPuff.
|
||||
FState *crashstate;
|
||||
if (hitthing == false && (crashstate = puff->FindState(NAME_Crash)) != NULL)
|
||||
if (!(flags & PF_HITTHING) && (crashstate = puff->FindState(NAME_Crash)) != NULL)
|
||||
{
|
||||
puff->SetState (crashstate);
|
||||
}
|
||||
else if (attackrange == MELEERANGE && puff->MeleeState != NULL)
|
||||
else if ((flags & PF_MELEERANGE) && puff->MeleeState != NULL)
|
||||
{
|
||||
// handle the hard coded state jump of Doom's bullet puff
|
||||
// in a more flexible manner.
|
||||
puff->SetState (puff->MeleeState);
|
||||
}
|
||||
|
||||
if (cl_pufftype && updown != 3 && !temporary && (puff->flags4 & MF4_ALLOWPARTICLES))
|
||||
if (!(flags & PF_TEMPORARY))
|
||||
{
|
||||
if (cl_pufftype && updown != 3 && (puff->flags4 & MF4_ALLOWPARTICLES))
|
||||
{
|
||||
P_DrawSplash2 (32, x, y, z, dir, updown, 1);
|
||||
puff->renderflags |= RF_INVISIBLE;
|
||||
}
|
||||
|
||||
if (!temporary)
|
||||
{
|
||||
if (hitthing && puff->SeeSound)
|
||||
if ((flags & PF_HITTHING) && puff->SeeSound)
|
||||
{ // Hit thing sound
|
||||
S_SoundID (puff, CHAN_BODY, puff->SeeSound, 1, ATTN_NORM);
|
||||
}
|
||||
|
@ -5099,6 +5136,13 @@ void AActor::Crash()
|
|||
}
|
||||
}
|
||||
|
||||
void AActor::SetIdle()
|
||||
{
|
||||
FState *idle = FindState (NAME_Idle);
|
||||
if (idle == NULL) idle = SpawnState;
|
||||
SetState(idle);
|
||||
}
|
||||
|
||||
FArchive &operator<< (FArchive &arc, FSoundIndex &snd)
|
||||
{
|
||||
if (arc.IsStoring ())
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "p_lnspec.h"
|
||||
#include "v_palette.h"
|
||||
#include "c_console.h"
|
||||
#include "c_cvars.h"
|
||||
#include "p_acs.h"
|
||||
#include "vectors.h"
|
||||
#include "announcer.h"
|
||||
|
@ -64,7 +65,7 @@
|
|||
|
||||
#include "fragglescript/t_fs.h"
|
||||
|
||||
extern void P_SpawnMapThing (mapthing2_t *mthing, int position);
|
||||
extern AActor *P_SpawnMapThing (mapthing2_t *mthing, int position);
|
||||
extern bool P_LoadBuildMap (BYTE *mapdata, size_t len, mapthing2_t **things, int *numthings);
|
||||
|
||||
extern void P_LoadTranslator(const char *lump);
|
||||
|
@ -283,7 +284,7 @@ MapData *P_OpenMapData(const char * mapname)
|
|||
if (lumpfile != nextfile)
|
||||
{
|
||||
// The following lump is from a different file so whatever this is,
|
||||
// it is not a multi-lump Doom level.
|
||||
// it is not a multi-lump Doom level so let's assume it is a Build map.
|
||||
return map;
|
||||
}
|
||||
|
||||
|
@ -383,6 +384,13 @@ MapData *P_OpenMapData(const char * mapname)
|
|||
return map;
|
||||
}
|
||||
|
||||
bool P_CheckMapData(const char *mapname)
|
||||
{
|
||||
MapData *mapd = P_OpenMapData(mapname);
|
||||
if (mapd == NULL) return false;
|
||||
delete mapd;
|
||||
return true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -1251,6 +1259,24 @@ void P_LoadNodes (MapData * map)
|
|||
delete[] mnp;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// SpawnMapThing
|
||||
//
|
||||
//===========================================================================
|
||||
CVAR(Bool, dumpspawnedthings, false, 0)
|
||||
|
||||
static void SpawnMapThing(int index, mapthing2_t *mt, int position)
|
||||
{
|
||||
AActor *spawned = P_SpawnMapThing(mt, position);
|
||||
if (dumpspawnedthings)
|
||||
{
|
||||
Printf("%5d: (%5d, %5d, %5d), doomednum = %5d, flags = %04x, type = %s\n",
|
||||
index, mt->x, mt->y, mt->z, mt->type, mt->flags,
|
||||
spawned? spawned->GetClass()->TypeName.GetChars() : "(none)");
|
||||
}
|
||||
T_AddSpawnedThing(spawned);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -1312,7 +1338,7 @@ void P_LoadThings (MapData * map, int position)
|
|||
mt2.angle = LittleShort(mt->angle);
|
||||
mt2.type = LittleShort(mt->type);
|
||||
|
||||
P_SpawnMapThing (&mt2, position);
|
||||
SpawnMapThing (i, &mt2, position);
|
||||
}
|
||||
delete [] mtp;
|
||||
}
|
||||
|
@ -1756,7 +1782,7 @@ void P_LoadThings2 (MapData * map, int position)
|
|||
|
||||
for (i=0, mt = (mapthing2_t*)mtp; i < numthings; i++,mt++)
|
||||
{
|
||||
P_SpawnMapThing (mt, position);
|
||||
SpawnMapThing (i, mt, position);
|
||||
}
|
||||
delete[] mtp;
|
||||
}
|
||||
|
@ -3869,7 +3895,7 @@ void P_SetupLevel (char *lumpname, int position)
|
|||
{
|
||||
for (i = 0; i < numbuildthings; ++i)
|
||||
{
|
||||
P_SpawnMapThing (&buildthings[i], 0);
|
||||
SpawnMapThing (i, &buildthings[i], 0);
|
||||
}
|
||||
delete[] buildthings;
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ struct MapData
|
|||
};
|
||||
|
||||
MapData * P_OpenMapData(const char * mapname);
|
||||
bool P_CheckMapData(const char * mapname);
|
||||
|
||||
// NOT called by W_Ticker. Fixme. [RH] Is that bad?
|
||||
//
|
||||
|
|
|
@ -475,6 +475,9 @@ static int TryFindSwitch (side_t *side, int Where)
|
|||
//
|
||||
bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno)
|
||||
{
|
||||
// if this line is one sided this function must always return success.
|
||||
if (line->sidenum[0] == NO_SIDE || line->sidenum[1] == NO_SIDE) return true;
|
||||
|
||||
fixed_t checktop;
|
||||
fixed_t checkbot;
|
||||
side_t *side = &sides[line->sidenum[sideno]];
|
||||
|
|
|
@ -267,7 +267,7 @@ void P_InitTerrainTypes ()
|
|||
lastlump = 0;
|
||||
while (-1 != (lump = Wads.FindLump ("TERRAIN", &lastlump)) )
|
||||
{
|
||||
FScanner sc(lump, "TERRAIN");
|
||||
FScanner sc(lump);
|
||||
ParseOuter (sc);
|
||||
}
|
||||
Splashes.ShrinkToFit ();
|
||||
|
|
|
@ -422,6 +422,7 @@ BEGIN_STATELESS_DEFAULTS (APlayerPawn, Any, -1, 0)
|
|||
PROP_PlayerPawn_SideMove2 (FRACUNIT)
|
||||
PROP_PlayerPawn_ColorRange (0, 0)
|
||||
PROP_PlayerPawn_SoundClass ("player")
|
||||
PROP_PlayerPawn_Face ("None")
|
||||
PROP_PlayerPawn_MorphWeapon ("None")
|
||||
END_DEFAULTS
|
||||
|
||||
|
|
|
@ -289,7 +289,7 @@ static void R_InitAnimDefs ()
|
|||
|
||||
while ((lump = Wads.FindLump ("ANIMDEFS", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump, "ANIMDEFS");
|
||||
FScanner sc(lump);
|
||||
|
||||
while (sc.GetString ())
|
||||
{
|
||||
|
|
|
@ -1103,7 +1103,7 @@ class FPlayerSkin
|
|||
{
|
||||
public:
|
||||
char name[17]; // 16 chars + NULL
|
||||
char face[3];
|
||||
char face[4]; // 3 chars ([MH] + NULL so can use as a C string)
|
||||
BYTE gender; // This skin's gender (not really used)
|
||||
BYTE range0start;
|
||||
BYTE range0end;
|
||||
|
|
|
@ -453,7 +453,7 @@ void R_InitSkins (void)
|
|||
sndlumps[j] = -1;
|
||||
skins[i].namespc = Wads.GetLumpNamespace (base);
|
||||
|
||||
FScanner sc(base, "S_SKIN");
|
||||
FScanner sc(base);
|
||||
intname = 0;
|
||||
crouchname = 0;
|
||||
|
||||
|
@ -501,6 +501,7 @@ void R_InitSkins (void)
|
|||
{
|
||||
for (j = 2; j >= 0; j--)
|
||||
skins[i].face[j] = toupper (sc.String[j]);
|
||||
skins[i].face[3] = '\0';
|
||||
}
|
||||
else if (0 == stricmp (key, "gender"))
|
||||
{
|
||||
|
@ -886,11 +887,20 @@ void R_InitSprites ()
|
|||
for (i = 0; i < PlayerClasses.Size (); i++)
|
||||
{
|
||||
const PClass *basetype = PlayerClasses[i].Type;
|
||||
const char *pclassface = basetype->Meta.GetMetaString (APMETA_Face);
|
||||
|
||||
strcpy (skins[i].name, "Base");
|
||||
if (strcmp(pclassface, "None") == 0)
|
||||
{
|
||||
skins[i].face[0] = 'S';
|
||||
skins[i].face[1] = 'T';
|
||||
skins[i].face[2] = 'F';
|
||||
skins[i].face[3] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(skins[i].face, pclassface);
|
||||
}
|
||||
skins[i].range0start = basetype->Meta.GetMetaInt (APMETA_ColorRange) & 255;
|
||||
skins[i].range0end = basetype->Meta.GetMetaInt (APMETA_ColorRange) >> 8;
|
||||
skins[i].Scale = GetDefaultByType (basetype)->scaleX;
|
||||
|
|
|
@ -561,7 +561,6 @@ int S_AddPlayerSound (const char *pclass, int gender, int refid,
|
|||
if (lumpname)
|
||||
{
|
||||
lump = Wads.CheckNumForFullName (lumpname, true, ns_sounds);
|
||||
if (lump == -1) lump = Wads.CheckNumForName (lumpname, ns_sounds);
|
||||
}
|
||||
|
||||
return S_AddPlayerSound (pclass, gender, refid, lump);
|
||||
|
@ -895,7 +894,7 @@ static void S_AddSNDINFO (int lump)
|
|||
bool skipToEndIf;
|
||||
TArray<WORD> list;
|
||||
|
||||
FScanner sc(lump, "SNDINFO");
|
||||
FScanner sc(lump);
|
||||
skipToEndIf = false;
|
||||
|
||||
while (sc.GetString ())
|
||||
|
|
|
@ -465,7 +465,7 @@ FArchive &operator<< (FArchive &arc, ReverbContainer *&env)
|
|||
return arc;
|
||||
}
|
||||
|
||||
static void ReadEAX (int lump, const char *lumpname)
|
||||
static void ReadEAX (int lump)
|
||||
{
|
||||
FScanner sc;
|
||||
const ReverbContainer *def;
|
||||
|
@ -476,7 +476,7 @@ static void ReadEAX (int lump, const char *lumpname)
|
|||
bool inited[NUM_EAX_FIELDS];
|
||||
BYTE bools[32];
|
||||
|
||||
sc.OpenLumpNum(lump, lumpname);
|
||||
sc.OpenLumpNum(lump);
|
||||
while (sc.GetString ())
|
||||
{
|
||||
name = copystring (sc.String);
|
||||
|
@ -576,7 +576,7 @@ void S_ParseSndEax ()
|
|||
|
||||
while ((lump = Wads.FindLump ("SNDEAX", &lastlump)) != -1)
|
||||
{
|
||||
ReadEAX (lump, "SNDEAX");
|
||||
ReadEAX (lump);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -432,7 +432,7 @@ static void AssignHexenTranslations (void)
|
|||
{
|
||||
for (seq = 0; seq < Sequences.Size(); seq++)
|
||||
{
|
||||
if (HexenSequences[i].Name == Sequences[seq]->SeqName)
|
||||
if (Sequences[seq] != NULL && HexenSequences[i].Name == Sequences[seq]->SeqName)
|
||||
break;
|
||||
}
|
||||
if (seq == Sequences.Size())
|
||||
|
@ -499,7 +499,7 @@ void S_ParseSndSeq (int levellump)
|
|||
lump = levellump;
|
||||
levellump = -2;
|
||||
}
|
||||
FScanner sc(lump, "SNDSEQ");
|
||||
FScanner sc(lump);
|
||||
while (sc.GetString ())
|
||||
{
|
||||
bool bDoorSound = false;
|
||||
|
@ -514,7 +514,7 @@ void S_ParseSndSeq (int levellump)
|
|||
seqtype = sc.String[0];
|
||||
for (curseq = 0; curseq < (int)Sequences.Size(); curseq++)
|
||||
{
|
||||
if (Sequences[curseq]->SeqName == seqname)
|
||||
if (Sequences[curseq] != NULL && Sequences[curseq]->SeqName == seqname)
|
||||
{
|
||||
M_Free (Sequences[curseq]);
|
||||
Sequences[curseq] = NULL;
|
||||
|
@ -684,6 +684,10 @@ void S_ParseSndSeq (int levellump)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (curseq > 0)
|
||||
{
|
||||
sc.ScriptError("End of file encountered before the final sequence ended.");
|
||||
}
|
||||
}
|
||||
|
||||
if (gameinfo.gametype == GAME_Hexen)
|
||||
|
@ -883,7 +887,7 @@ static int FindSequence (FName seqname)
|
|||
|
||||
for (i = Sequences.Size(); i-- > 0; )
|
||||
{
|
||||
if (seqname == Sequences[i]->SeqName)
|
||||
if (Sequences[i] != NULL && seqname == Sequences[i]->SeqName)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -379,7 +379,7 @@ void S_Start ()
|
|||
if (*LocalSndInfo)
|
||||
{
|
||||
// Now parse the local SNDINFO
|
||||
int j = Wads.CheckNumForName(LocalSndInfo);
|
||||
int j = Wads.CheckNumForFullName(LocalSndInfo, true);
|
||||
if (j>=0) S_AddLocalSndInfo(j);
|
||||
}
|
||||
|
||||
|
@ -392,7 +392,7 @@ void S_Start ()
|
|||
}
|
||||
if (parse_ss)
|
||||
{
|
||||
S_ParseSndSeq(*LocalSndSeq? Wads.CheckNumForName(LocalSndSeq) : -1);
|
||||
S_ParseSndSeq(*LocalSndSeq? Wads.CheckNumForFullName(LocalSndSeq, true) : -1);
|
||||
}
|
||||
else
|
||||
|
||||
|
@ -715,7 +715,8 @@ static void S_StartSound (fixed_t *pt, AActor *mover, int channel,
|
|||
|
||||
// If this sound doesn't like playing near itself, don't play it if
|
||||
// that's what would happen.
|
||||
if (NearLimit > 0 && pt != NULL && S_CheckSoundLimit(sfx, pos, NearLimit))
|
||||
if (NearLimit > 0 && pt != NULL && mover != players[consoleplayer].camera &&
|
||||
S_CheckSoundLimit(sfx, pos, NearLimit))
|
||||
return;
|
||||
|
||||
// Make sure the sound is loaded.
|
||||
|
|
|
@ -91,10 +91,10 @@ FScanner::FScanner(const FScanner &other)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FScanner::FScanner(int lumpnum, const char *name)
|
||||
FScanner::FScanner(int lumpnum)
|
||||
{
|
||||
ScriptOpen = false;
|
||||
OpenLumpNum(lumpnum, name);
|
||||
OpenLumpNum(lumpnum);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -169,7 +169,7 @@ void FScanner::Open (const char *name)
|
|||
{
|
||||
I_Error("Could not find script lump '%s'\n", name);
|
||||
}
|
||||
OpenLumpNum(lump, name);
|
||||
OpenLumpNum(lump);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -219,14 +219,14 @@ void FScanner::OpenMem (const char *name, char *buffer, int size)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FScanner :: OpenLumpNum (int lump, const char *name)
|
||||
void FScanner :: OpenLumpNum (int lump)
|
||||
{
|
||||
Close ();
|
||||
{
|
||||
FMemLump mem = Wads.ReadLump(lump);
|
||||
ScriptBuffer = mem.GetString();
|
||||
}
|
||||
ScriptName = name;
|
||||
ScriptName = Wads.GetLumpFullPath(lump);
|
||||
PrepareScript ();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ public:
|
|||
// Methods ------------------------------------------------------
|
||||
FScanner();
|
||||
FScanner(const FScanner &other);
|
||||
FScanner(int lumpnum, const char *name);
|
||||
FScanner(int lumpnum);
|
||||
~FScanner();
|
||||
|
||||
FScanner &operator=(const FScanner &other);
|
||||
|
@ -21,7 +21,7 @@ public:
|
|||
void Open(const char *lumpname);
|
||||
void OpenFile(const char *filename);
|
||||
void OpenMem(const char *name, char *buffer, int size);
|
||||
void OpenLumpNum(int lump, const char *name);
|
||||
void OpenLumpNum(int lump);
|
||||
void Close();
|
||||
|
||||
void SetCMode(bool cmode);
|
||||
|
|
|
@ -1191,7 +1191,7 @@ FMOD_MODE FMODSoundRenderer::SetChanHeadSettings(FMOD::Channel *chan, sfxinfo_t
|
|||
{
|
||||
return oldmode;
|
||||
}
|
||||
double cpos[3];
|
||||
float cpos[3];
|
||||
cpos[0] = FIXED2FLOAT(players[consoleplayer].camera->x);
|
||||
cpos[2] = FIXED2FLOAT(players[consoleplayer].camera->y);
|
||||
cpos[1] = FIXED2FLOAT(players[consoleplayer].camera->z);
|
||||
|
@ -1226,11 +1226,11 @@ FMOD_MODE FMODSoundRenderer::SetChanHeadSettings(FMOD::Channel *chan, sfxinfo_t
|
|||
return oldmode;
|
||||
}
|
||||
else if (cpos[0] == pos[0] && cpos[1] == pos[1] && cpos[2] == pos[2])
|
||||
{
|
||||
pos[2] = pos[1] = pos[0] = 0;
|
||||
return (oldmode & ~FMOD_3D_WORLDRELATIVE) | FMOD_3D_HEADRELATIVE;
|
||||
{ // Head relative
|
||||
return (oldmode & ~FMOD_3D) | FMOD_2D;
|
||||
}
|
||||
return (oldmode & ~FMOD_3D_HEADRELATIVE) | FMOD_3D_WORLDRELATIVE;
|
||||
// World relative
|
||||
return (oldmode & ~FMOD_2D) | FMOD_3D;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1556,15 +1556,9 @@ void FMODSoundRenderer::DoLoad(void **slot, sfxinfo_t *sfx)
|
|||
exinfo.length = size;
|
||||
}
|
||||
result = Sys->createSound((char *)sfxstart, samplemode, &exinfo, &sample);
|
||||
if (result == FMOD_ERR_OUTPUT_CREATEBUFFER && !(samplemode & FMOD_SOFTWARE))
|
||||
{
|
||||
DPrintf("Trying to fall back to software sample\n");
|
||||
samplemode = (samplemode & ~FMOD_HARDWARE) | FMOD_SOFTWARE;
|
||||
result = Sys->createSound((char *)sfxstart, samplemode, &exinfo, &sample);
|
||||
}
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
DPrintf("Failed to allocate sample: %d\n", result);
|
||||
DPrintf("Failed to allocate sample: Error %d\n", result);
|
||||
errcount++;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -147,6 +147,11 @@ FString MusInfo::GetStats()
|
|||
return "No stats available for this song";
|
||||
}
|
||||
|
||||
MusInfo *MusInfo::GetOPLDumper(const char *filename)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void I_InitMusic (void)
|
||||
{
|
||||
static bool setatterm = false;
|
||||
|
@ -304,7 +309,6 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le
|
|||
/* MUS are played as:
|
||||
- OPL:
|
||||
- if explicitly selected by $mididevice
|
||||
- when opl_enable is true and no midi device is set for the song
|
||||
- when snd_mididevice is -3 and no midi device is set for the song
|
||||
|
||||
Timidity:
|
||||
|
@ -321,9 +325,9 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le
|
|||
- when snd_mididevice is >= 0 and no midi device is set for the song
|
||||
- as fallback when both OPL and Timidity failed and snd_mididevice is >= 0
|
||||
*/
|
||||
if (((opl_enable || snd_mididevice == -3) && device == MDEV_DEFAULT) || device == MDEV_OPL)
|
||||
if ((snd_mididevice == -3 && device == MDEV_DEFAULT) || device == MDEV_OPL)
|
||||
{
|
||||
info = new OPLMUSSong (file, musiccache, len);
|
||||
info = new MUSSong2 (file, musiccache, len, true);
|
||||
}
|
||||
else if (device == MDEV_TIMIDITY || (device == MDEV_DEFAULT && snd_mididevice == -2))
|
||||
{
|
||||
|
@ -369,7 +373,7 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le
|
|||
#ifdef _WIN32
|
||||
if (info == NULL)
|
||||
{
|
||||
info = new MUSSong2 (file, musiccache, len);
|
||||
info = new MUSSong2 (file, musiccache, len, false);
|
||||
}
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
@ -384,7 +388,6 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le
|
|||
/* MIDI are played as:
|
||||
OPL:
|
||||
- if explicitly selected by $mididevice
|
||||
- when opl_enable is true and no midi device is set for the song
|
||||
- when snd_mididevice is -3 and no midi device is set for the song
|
||||
|
||||
Timidity:
|
||||
|
@ -422,8 +425,11 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le
|
|||
}
|
||||
#endif // _WIN32
|
||||
}
|
||||
// Check for RDosPlay raw OPL format
|
||||
else if (id == MAKE_ID('R','A','W','A') && len >= 12)
|
||||
// Check for various raw OPL formats
|
||||
else if (len >= 12 &&
|
||||
(id == MAKE_ID('R','A','W','A') || // Rdos Raw OPL
|
||||
id == MAKE_ID('D','B','R','A') || // DosBox Raw OPL
|
||||
id == MAKE_ID('A','D','L','I'))) // Martin Fernandez's modified IMF
|
||||
{
|
||||
DWORD fullsig[2];
|
||||
|
||||
|
@ -441,30 +447,9 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le
|
|||
memcpy(fullsig, musiccache, 8);
|
||||
}
|
||||
|
||||
if (fullsig[1] == MAKE_ID('D','A','T','A'))
|
||||
{
|
||||
info = new OPLMUSSong (file, musiccache, len);
|
||||
}
|
||||
}
|
||||
// Check for Martin Fernandez's modified IMF format
|
||||
else if (id == MAKE_ID('A','D','L','I'))
|
||||
{
|
||||
char fullhead[6];
|
||||
|
||||
if (file != NULL)
|
||||
{
|
||||
if (fread (fullhead, 1, 6, file) != 6)
|
||||
{
|
||||
fclose (file);
|
||||
return 0;
|
||||
}
|
||||
fseek (file, -6, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(fullhead, musiccache, 6);
|
||||
}
|
||||
if (fullhead[4] == 'B' && fullhead[5] == 1)
|
||||
if ((fullsig[0] == MAKE_ID('R','A','W','A') && fullsig[1] == MAKE_ID('D','A','T','A')) ||
|
||||
(fullsig[0] == MAKE_ID('D','B','R','A') && fullsig[1] == MAKE_ID('W','O','P','L')) ||
|
||||
(fullsig[0] == MAKE_ID('A','D','L','I') && (fullsig[1] & MAKE_ID(255,255,0,0)) == MAKE_ID('B',1,0,0)))
|
||||
{
|
||||
info = new OPLMUSSong (file, musiccache, len);
|
||||
}
|
||||
|
@ -597,3 +582,40 @@ ADD_STAT(music)
|
|||
}
|
||||
return "No song playing";
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CCMD writeopl
|
||||
//
|
||||
// If the current song can be played with OPL instruments, dump it to
|
||||
// the specified file on disk.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CCMD (writeopl)
|
||||
{
|
||||
if (argv.argc() == 2)
|
||||
{
|
||||
if (currSong == NULL)
|
||||
{
|
||||
Printf ("No song is currently playing.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
MusInfo *dumper = currSong->GetOPLDumper(argv[1]);
|
||||
if (dumper == NULL)
|
||||
{
|
||||
Printf ("Current song cannot be saved as OPL data.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
dumper->Play(false);
|
||||
delete dumper;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("Usage: writeopl <filename>");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ public:
|
|||
virtual bool SetPosition (int order);
|
||||
virtual void Update();
|
||||
virtual FString GetStats();
|
||||
virtual MusInfo *GetOPLDumper(const char *filename);
|
||||
|
||||
enum EState
|
||||
{
|
||||
|
@ -152,7 +153,7 @@ protected:
|
|||
|
||||
// OPL implementation of a MIDI output device -------------------------------
|
||||
|
||||
class OPLMIDIDevice : public MIDIDevice, OPLmusicBlock
|
||||
class OPLMIDIDevice : public MIDIDevice, protected OPLmusicBlock
|
||||
{
|
||||
public:
|
||||
OPLMIDIDevice();
|
||||
|
@ -191,6 +192,17 @@ protected:
|
|||
DWORD Position;
|
||||
};
|
||||
|
||||
// OPL dumper implementation of a MIDI output device ------------------------
|
||||
|
||||
class OPLDumperMIDIDevice : public OPLMIDIDevice
|
||||
{
|
||||
public:
|
||||
OPLDumperMIDIDevice(const char *filename);
|
||||
~OPLDumperMIDIDevice();
|
||||
int Resume();
|
||||
void Stop();
|
||||
};
|
||||
|
||||
// Base class for streaming MUS and MIDI files ------------------------------
|
||||
|
||||
class MIDIStreamer : public MusInfo
|
||||
|
@ -210,13 +222,15 @@ public:
|
|||
void Update();
|
||||
|
||||
protected:
|
||||
static void Callback(unsigned int uMsg, void *userdata, DWORD dwParam1, DWORD dwParam2);
|
||||
MIDIStreamer(const char *dumpname);
|
||||
|
||||
void OutputVolume (DWORD volume);
|
||||
int FillBuffer(int buffer_num, int max_events, DWORD max_time);
|
||||
bool ServiceEvent();
|
||||
int VolumeControllerChange(int channel, int volume);
|
||||
|
||||
static void Callback(unsigned int uMsg, void *userdata, DWORD dwParam1, DWORD dwParam2);
|
||||
|
||||
// Virtuals for subclasses to override
|
||||
virtual void CheckCaps();
|
||||
virtual void DoInitialSetup() = 0;
|
||||
|
@ -261,6 +275,7 @@ protected:
|
|||
DWORD Volume;
|
||||
bool UseOPLDevice;
|
||||
bool CallbackIsThreaded;
|
||||
FString DumpFilename;
|
||||
};
|
||||
|
||||
// MUS file played with a MIDI stream ---------------------------------------
|
||||
|
@ -268,10 +283,14 @@ protected:
|
|||
class MUSSong2 : public MIDIStreamer
|
||||
{
|
||||
public:
|
||||
MUSSong2 (FILE *file, char *musiccache, int length);
|
||||
~MUSSong2 ();
|
||||
MUSSong2(FILE *file, char *musiccache, int length, bool opl);
|
||||
~MUSSong2();
|
||||
|
||||
MusInfo *GetOPLDumper(const char *filename);
|
||||
|
||||
protected:
|
||||
MUSSong2(const MUSSong2 *original, const char *filename); //OPL dump constructor
|
||||
|
||||
void DoInitialSetup();
|
||||
void DoRestart();
|
||||
bool CheckDone();
|
||||
|
@ -288,10 +307,14 @@ protected:
|
|||
class MIDISong2 : public MIDIStreamer
|
||||
{
|
||||
public:
|
||||
MIDISong2 (FILE *file, char *musiccache, int length, bool opl);
|
||||
~MIDISong2 ();
|
||||
MIDISong2(FILE *file, char *musiccache, int length, bool opl);
|
||||
~MIDISong2();
|
||||
|
||||
MusInfo *GetOPLDumper(const char *filename);
|
||||
|
||||
protected:
|
||||
MIDISong2(const MIDISong2 *original, const char *filename); // OPL dump constructor
|
||||
|
||||
void CheckCaps();
|
||||
void DoInitialSetup();
|
||||
void DoRestart();
|
||||
|
@ -307,6 +330,7 @@ protected:
|
|||
void SetTempo(int new_tempo);
|
||||
|
||||
BYTE *MusHeader;
|
||||
int SongLen;
|
||||
TrackInfo *Tracks;
|
||||
TrackInfo *TrackDue;
|
||||
int NumTracks;
|
||||
|
@ -381,19 +405,29 @@ protected:
|
|||
class OPLMUSSong : public StreamSong
|
||||
{
|
||||
public:
|
||||
OPLMUSSong (FILE *file, char * musiccache, int length);
|
||||
OPLMUSSong (FILE *file, char *musiccache, int length);
|
||||
~OPLMUSSong ();
|
||||
void Play (bool looping);
|
||||
bool IsPlaying ();
|
||||
bool IsValid () const;
|
||||
void ResetChips ();
|
||||
MusInfo *GetOPLDumper(const char *filename);
|
||||
|
||||
protected:
|
||||
OPLMUSSong(const OPLMUSSong *original, const char *filename); // OPL dump constructor
|
||||
|
||||
static bool FillStream (SoundStream *stream, void *buff, int len, void *userdata);
|
||||
|
||||
OPLmusicFile *Music;
|
||||
};
|
||||
|
||||
class OPLMUSDumper : public OPLMUSSong
|
||||
{
|
||||
public:
|
||||
OPLMUSDumper(const OPLMUSSong *original, const char *filename);
|
||||
void Play(bool looping);
|
||||
};
|
||||
|
||||
// CD track/disk played through the multimedia system -----------------------
|
||||
|
||||
class CDSong : public MusInfo
|
||||
|
@ -430,4 +464,3 @@ extern MusInfo *currSong;
|
|||
extern int nomusic;
|
||||
|
||||
EXTERN_CVAR (Float, snd_musicvolume)
|
||||
EXTERN_CVAR (Bool, opl_enable)
|
||||
|
|
|
@ -44,8 +44,6 @@
|
|||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#define MAX_TIME (1000000/20) // Send out 1/20 of a sec of events at a time.
|
||||
|
||||
// Used by SendCommand to check for unexpected end-of-track conditions.
|
||||
#define CHECK_FINISHED \
|
||||
if (track->TrackP >= track->MaxTrackP) \
|
||||
|
@ -115,6 +113,7 @@ MIDISong2::MIDISong2 (FILE *file, char *musiccache, int len, bool opl)
|
|||
}
|
||||
#endif
|
||||
MusHeader = new BYTE[len];
|
||||
SongLen = len;
|
||||
if (file != NULL)
|
||||
{
|
||||
if (fread(MusHeader, 1, len, file) != (size_t)len)
|
||||
|
@ -754,3 +753,43 @@ void MIDISong2::SetTempo(int new_tempo)
|
|||
Tempo = new_tempo;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDISong2 :: GetOPLDumper
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
MusInfo *MIDISong2::GetOPLDumper(const char *filename)
|
||||
{
|
||||
return new MIDISong2(this, filename);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDISong2 OPL Dumping Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
MIDISong2::MIDISong2(const MIDISong2 *original, const char *filename)
|
||||
: MIDIStreamer(filename)
|
||||
{
|
||||
SongLen = original->SongLen;
|
||||
MusHeader = new BYTE[original->SongLen];
|
||||
memcpy(MusHeader, original->MusHeader, original->SongLen);
|
||||
Format = original->Format;
|
||||
NumTracks = original->NumTracks;
|
||||
DesignationMask = 0;
|
||||
Division = original->Division;
|
||||
Tempo = InitialTempo = original->InitialTempo;
|
||||
Tracks = new TrackInfo[NumTracks];
|
||||
for (int i = 0; i < NumTracks; ++i)
|
||||
{
|
||||
TrackInfo *newtrack = &Tracks[i];
|
||||
const TrackInfo *oldtrack = &original->Tracks[i];
|
||||
|
||||
newtrack->TrackBegin = MusHeader + (oldtrack->TrackBegin - original->MusHeader);
|
||||
newtrack->TrackP = 0;
|
||||
newtrack->MaxTrackP = oldtrack->MaxTrackP;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,11 +70,11 @@ extern UINT mididevice;
|
|||
//==========================================================================
|
||||
|
||||
MIDIStreamer::MIDIStreamer(bool opl)
|
||||
: MIDI(0),
|
||||
:
|
||||
#ifdef _WIN32
|
||||
PlayerThread(0), ExitEvent(0), BufferDoneEvent(0),
|
||||
#endif
|
||||
Division(0), InitialTempo(500000), UseOPLDevice(opl)
|
||||
MIDI(0), Division(0), InitialTempo(500000), UseOPLDevice(opl)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
BufferDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
|
@ -91,6 +91,25 @@ MIDIStreamer::MIDIStreamer(bool opl)
|
|||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIStreamer OPL Dumping Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
MIDIStreamer::MIDIStreamer(const char *dumpname)
|
||||
:
|
||||
#ifdef _WIN32
|
||||
PlayerThread(0), ExitEvent(0), BufferDoneEvent(0),
|
||||
#endif
|
||||
MIDI(0), Division(0), InitialTempo(500000), UseOPLDevice(true), DumpFilename(dumpname)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
BufferDoneEvent = NULL;
|
||||
ExitEvent = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIStreamer Destructor
|
||||
|
@ -163,7 +182,7 @@ void MIDIStreamer::CheckCaps()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIStreamer::Play (bool looping)
|
||||
void MIDIStreamer::Play(bool looping)
|
||||
{
|
||||
DWORD tid;
|
||||
|
||||
|
@ -175,6 +194,11 @@ void MIDIStreamer::Play (bool looping)
|
|||
InitialPlayback = true;
|
||||
|
||||
assert(MIDI == NULL);
|
||||
if (DumpFilename.IsNotEmpty())
|
||||
{
|
||||
MIDI = new OPLDumperMIDIDevice(DumpFilename);
|
||||
}
|
||||
else
|
||||
#ifdef _WIN32
|
||||
if (!UseOPLDevice)
|
||||
{
|
||||
|
@ -281,7 +305,7 @@ void MIDIStreamer::Play (bool looping)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIStreamer::Pause ()
|
||||
void MIDIStreamer::Pause()
|
||||
{
|
||||
if (m_Status == STATE_Playing)
|
||||
{
|
||||
|
@ -302,7 +326,7 @@ void MIDIStreamer::Pause ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIStreamer::Resume ()
|
||||
void MIDIStreamer::Resume()
|
||||
{
|
||||
if (m_Status == STATE_Paused)
|
||||
{
|
||||
|
@ -322,7 +346,7 @@ void MIDIStreamer::Resume ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIStreamer::Stop ()
|
||||
void MIDIStreamer::Stop()
|
||||
{
|
||||
EndQueued = 2;
|
||||
#ifdef _WIN32
|
||||
|
@ -355,7 +379,7 @@ void MIDIStreamer::Stop ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool MIDIStreamer::IsPlaying ()
|
||||
bool MIDIStreamer::IsPlaying()
|
||||
{
|
||||
return m_Status != STATE_Stopped;
|
||||
}
|
||||
|
@ -369,7 +393,7 @@ bool MIDIStreamer::IsPlaying ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void MIDIStreamer::MusicVolumeChanged ()
|
||||
void MIDIStreamer::MusicVolumeChanged()
|
||||
{
|
||||
if (MIDI->FakeVolume())
|
||||
{
|
||||
|
@ -676,7 +700,7 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, DWORD max_time)
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIDevice constructor and desctructor stubs.
|
||||
// MIDIDevice stubs.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
**---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include "i_musicinterns.h"
|
||||
|
@ -52,8 +50,6 @@
|
|||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern UINT mididevice;
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static const BYTE CtrlTranslate[15] =
|
||||
|
@ -88,13 +84,15 @@ static const BYTE CtrlTranslate[15] =
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
MUSSong2::MUSSong2 (FILE *file, char *musiccache, int len)
|
||||
: MIDIStreamer(false), MusHeader(0), MusBuffer(0)
|
||||
MUSSong2::MUSSong2 (FILE *file, char *musiccache, int len, bool opl)
|
||||
: MIDIStreamer(opl), MusHeader(0), MusBuffer(0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (ExitEvent == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
MusHeader = (MUSHeader *)new BYTE[len];
|
||||
if (file != NULL)
|
||||
|
@ -304,4 +302,32 @@ end:
|
|||
}
|
||||
return events;
|
||||
}
|
||||
#endif
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MUSSong2 :: GetOPLDumper
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
MusInfo *MUSSong2::GetOPLDumper(const char *filename)
|
||||
{
|
||||
return new MUSSong2(this, filename);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MUSSong2 OPL Dumping Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
MUSSong2::MUSSong2(const MUSSong2 *original, const char *filename)
|
||||
: MIDIStreamer(filename)
|
||||
{
|
||||
int songstart = LittleShort(original->MusHeader->SongStart);
|
||||
MaxMusP = original->MaxMusP;
|
||||
MusHeader = (MUSHeader *)new BYTE[songstart + MaxMusP];
|
||||
memcpy(MusHeader, original->MusHeader, songstart + MaxMusP);
|
||||
MusBuffer = (BYTE *)MusHeader + songstart;
|
||||
Division = 140;
|
||||
InitialTempo = 1000000;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "i_musicinterns.h"
|
||||
|
||||
CVAR (Bool, opl_enable, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
||||
static bool OPL_Active;
|
||||
|
||||
CUSTOM_CVAR (Bool, opl_onechip, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
|
@ -12,12 +10,11 @@ CUSTOM_CVAR (Bool, opl_onechip, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
OPLMUSSong::OPLMUSSong (FILE *file, char *musiccache, int len)
|
||||
{
|
||||
int samples = int(OPL_SAMPLE_RATE / 14);
|
||||
|
||||
Music = new OPLmusicFile (file, musiccache, len, samples);
|
||||
Music = new OPLmusicFile (file, musiccache, len);
|
||||
|
||||
m_Stream = GSnd->CreateStream (FillStream, samples*4,
|
||||
SoundStream::Mono | SoundStream::Float, int(OPL_SAMPLE_RATE), this);
|
||||
|
@ -63,7 +60,7 @@ void OPLMUSSong::Play (bool looping)
|
|||
Music->SetLooping (looping);
|
||||
Music->Restart ();
|
||||
|
||||
if (m_Stream->Play (true, snd_musicvolume, false))
|
||||
if (m_Stream == NULL || m_Stream->Play (true, snd_musicvolume, false))
|
||||
{
|
||||
m_Status = STATE_Playing;
|
||||
}
|
||||
|
@ -74,3 +71,24 @@ bool OPLMUSSong::FillStream (SoundStream *stream, void *buff, int len, void *use
|
|||
OPLMUSSong *song = (OPLMUSSong *)userdata;
|
||||
return song->Music->ServiceStream (buff, len);
|
||||
}
|
||||
|
||||
MusInfo *OPLMUSSong::GetOPLDumper(const char *filename)
|
||||
{
|
||||
return new OPLMUSDumper(this, filename);
|
||||
}
|
||||
|
||||
OPLMUSSong::OPLMUSSong(const OPLMUSSong *original, const char *filename)
|
||||
{
|
||||
Music = new OPLmusicFile(original->Music, filename);
|
||||
m_Stream = NULL;
|
||||
}
|
||||
|
||||
OPLMUSDumper::OPLMUSDumper(const OPLMUSSong *original, const char *filename)
|
||||
: OPLMUSSong(original, filename)
|
||||
{
|
||||
}
|
||||
|
||||
void OPLMUSDumper::Play(bool looping)
|
||||
{
|
||||
Music->Dump();
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ void FStringTable::LoadLanguage (int lumpnum, DWORD code, bool exactMatch, int p
|
|||
|
||||
code |= orMask;
|
||||
|
||||
FScanner sc(lumpnum, "LANGUAGE");
|
||||
FScanner sc(lumpnum);
|
||||
sc.SetCMode (true);
|
||||
while (sc.GetString ())
|
||||
{
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
// This file was automatically generated by the
|
||||
// updaterevision tool. Do not edit by hand.
|
||||
|
||||
#define ZD_SVN_REVISION_STRING "871"
|
||||
#define ZD_SVN_REVISION_NUMBER 871
|
||||
#define ZD_SVN_REVISION_STRING "882"
|
||||
#define ZD_SVN_REVISION_NUMBER 882
|
||||
|
|
|
@ -84,7 +84,7 @@ void TEAMINFO_Init ()
|
|||
|
||||
while ((lump = Wads.FindLump ("TEAMINFO", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump, "TEAMINFO");
|
||||
FScanner sc(lump);
|
||||
while (sc.GetString ())
|
||||
{
|
||||
if (sc.Compare("CLEARTEAMS"))
|
||||
|
|
|
@ -508,7 +508,7 @@ void FTextureManager::LoadHiresTex(int wadnum)
|
|||
{
|
||||
if (Wads.GetLumpFile(remapLump) == wadnum)
|
||||
{
|
||||
FScanner sc(remapLump, "HIRESTEX");
|
||||
FScanner sc(remapLump);
|
||||
while (sc.GetString())
|
||||
{
|
||||
if (sc.Compare("remap")) // remap an existing texture
|
||||
|
|
|
@ -1145,7 +1145,7 @@ void A_CustomPunch (AActor *self)
|
|||
PuffType = PClass::FindClass(PuffTypeName);
|
||||
if (!PuffType) PuffType = PClass::FindClass(NAME_BulletPuff);
|
||||
|
||||
P_LineAttack (self, angle, Range, pitch, Damage, GetDefaultByType(PuffType)->DamageType, PuffType);
|
||||
P_LineAttack (self, angle, Range, pitch, Damage, GetDefaultByType(PuffType)->DamageType, PuffType, true);
|
||||
|
||||
// turn to face target
|
||||
if (linetarget)
|
||||
|
|
|
@ -150,7 +150,7 @@ void LoadDecorations ()
|
|||
lastlump = 0;
|
||||
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump, Wads.GetLumpFullName(lump));
|
||||
FScanner sc(lump);
|
||||
ParseDecorate (sc);
|
||||
}
|
||||
FinishThingdef();
|
||||
|
|
|
@ -235,6 +235,7 @@ static flagdef ActorFlags[]=
|
|||
DEFINE_FLAG(MF5, NEVERRESPAWN, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, DONTRIP, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOINFIGHTING, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOINTERACTION, AActor, flags5),
|
||||
|
||||
// Effect flags
|
||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||
|
@ -2183,6 +2184,36 @@ static void PlayerSoundClass (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
|
|||
bag.Info->Class->Meta.SetMetaString (APMETA_SoundClass, tmp);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
static void PlayerFace (FScanner &sc, APlayerPawn *defaults, Baggage &bag)
|
||||
{
|
||||
FString tmp;
|
||||
|
||||
sc.MustGetString ();
|
||||
tmp = sc.String;
|
||||
if (tmp.Len() != 3)
|
||||
{
|
||||
Printf("Invalid face '%s' for '%s';\nSTF replacement codes must be 3 characters.\n",
|
||||
sc.String, bag.Info->Class->TypeName.GetChars ());
|
||||
}
|
||||
|
||||
tmp.ToUpper();
|
||||
bool valid = (
|
||||
(((tmp[0] >= 'A') && (tmp[0] <= 'Z')) || ((tmp[0] >= '0') && (tmp[0] <= '9'))) &&
|
||||
(((tmp[1] >= 'A') && (tmp[1] <= 'Z')) || ((tmp[1] >= '0') && (tmp[1] <= '9'))) &&
|
||||
(((tmp[2] >= 'A') && (tmp[2] <= 'Z')) || ((tmp[2] >= '0') && (tmp[2] <= '9')))
|
||||
);
|
||||
if (!valid)
|
||||
{
|
||||
Printf("Invalid face '%s' for '%s';\nSTF replacement codes must be alphanumeric.\n",
|
||||
sc.String, bag.Info->Class->TypeName.GetChars ());
|
||||
}
|
||||
|
||||
bag.Info->Class->Meta.SetMetaString (APMETA_Face, tmp);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
@ -2551,6 +2582,7 @@ static const ActorProps props[] =
|
|||
{ "player.crouchsprite", (apf)PlayerCrouchSprite, RUNTIME_CLASS(APlayerPawn) },
|
||||
{ "player.damagescreencolor", (apf)PlayerDmgScreenColor, RUNTIME_CLASS(APlayerPawn) },
|
||||
{ "player.displayname", (apf)PlayerDisplayName, RUNTIME_CLASS(APlayerPawn) },
|
||||
{ "player.face", (apf)PlayerFace, RUNTIME_CLASS(APlayerPawn) },
|
||||
{ "player.forwardmove", (apf)PlayerForwardMove, RUNTIME_CLASS(APlayerPawn) },
|
||||
{ "player.healradiustype", (apf)PlayerHealRadius, RUNTIME_CLASS(APlayerPawn) },
|
||||
{ "player.hexenarmor", (apf)PlayerHexenArmor, RUNTIME_CLASS(APlayerPawn) },
|
||||
|
|
|
@ -218,12 +218,6 @@ FFont *V_GetFont(const char *name)
|
|||
int lump = -1;
|
||||
|
||||
lump = Wads.CheckNumForFullName(name, true);
|
||||
if (lump < 0 && strlen(name) > 8)
|
||||
{
|
||||
FString fullname;
|
||||
fullname.Format("%s.fon", name);
|
||||
lump = Wads.CheckNumForFullName(fullname);
|
||||
}
|
||||
|
||||
if (lump != -1)
|
||||
{
|
||||
|
@ -293,6 +287,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
|
|||
double *luminosity;
|
||||
int maxyoffs;
|
||||
bool doomtemplate = gameinfo.gametype == GAME_Doom ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
|
||||
bool stcfn121 = false;
|
||||
|
||||
Chars = new CharData[count];
|
||||
charlumps = new int[count];
|
||||
|
@ -314,17 +309,22 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
|
|||
lump = Wads.CheckNumForName (buffer, ns_graphics);
|
||||
if (doomtemplate && lump >= 0 && i + start == 121)
|
||||
{ // HACKHACK: Don't load STCFN121 in doom(2), because
|
||||
// it's not really a lower-case 'y' but an upper-case 'I'.
|
||||
// it's not really a lower-case 'y' but a '|'.
|
||||
// Because a lot of wads with their own font seem to foolishly
|
||||
// copy STCFN121 and make it an 'I' themselves, wads must
|
||||
// copy STCFN121 and make it a '|' themselves, wads must
|
||||
// provide STCFN120 (x) and STCFN122 (z) for STCFN121 to load.
|
||||
if (Wads.CheckNumForName ("STCFN120", ns_graphics) == -1 ||
|
||||
Wads.CheckNumForName ("STCFN122", ns_graphics) == -1)
|
||||
{
|
||||
// insert the incorrectly named '|' graphic in its correct position.
|
||||
if (count > 124-start) charlumps[124-start] = lump;
|
||||
lump = -1;
|
||||
stcfn121 = true;
|
||||
}
|
||||
}
|
||||
if (lump != -1 || i != 124-start || !stcfn121)
|
||||
charlumps[i] = lump;
|
||||
|
||||
if (lump >= 0)
|
||||
{
|
||||
FTexture *pic = TexMan[buffer];
|
||||
|
@ -1631,7 +1631,7 @@ void V_InitCustomFonts()
|
|||
|
||||
while ((llump = Wads.FindLump ("FONTDEFS", &lastlump)) != -1)
|
||||
{
|
||||
sc.OpenLumpNum(llump, "FONTDEFS");
|
||||
sc.OpenLumpNum(llump);
|
||||
while (sc.GetString())
|
||||
{
|
||||
memset (lumplist, -1, sizeof(lumplist));
|
||||
|
@ -1691,7 +1691,7 @@ void V_InitCustomFonts()
|
|||
if (format == 1) goto wrong;
|
||||
int *p = &lumplist[*(unsigned char*)sc.String];
|
||||
sc.MustGetString();
|
||||
*p = Wads.CheckNumForName (sc.String);
|
||||
*p = Wads.CheckNumForFullName (sc.String, true);
|
||||
format=2;
|
||||
}
|
||||
}
|
||||
|
@ -1759,7 +1759,7 @@ void V_InitFontColors ()
|
|||
|
||||
while ((lump = Wads.FindLump ("TEXTCOLO", &lastlump)) != -1)
|
||||
{
|
||||
FScanner sc(lump, "textcolors.txt");
|
||||
FScanner sc(lump);
|
||||
while (sc.GetString())
|
||||
{
|
||||
names.Clear();
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
// SAVESIG should match SAVEVER.
|
||||
|
||||
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
||||
#define MINSAVEVER 854
|
||||
#define MINSAVEVER 879
|
||||
|
||||
#if ZD_SVN_REVISION_NUMBER < MINSAVEVER
|
||||
// Never write a savegame with a version lower than what we need
|
||||
|
|
|
@ -1617,6 +1617,25 @@ const char *FWadCollection::GetLumpFullName (int lump) const
|
|||
return LumpInfo[lump].name;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FWadCollection :: GetLumpFullPath
|
||||
//
|
||||
// Returns the name of the lump's wad prefixed to the lump's full name.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FString FWadCollection::GetLumpFullPath(int lump) const
|
||||
{
|
||||
FString foo;
|
||||
|
||||
if ((size_t) lump < NumLumps)
|
||||
{
|
||||
foo << GetWadName(LumpInfo[lump].wadnum) << ':' << GetLumpFullName(lump);
|
||||
}
|
||||
return foo;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetLumpNamespace
|
||||
|
|
|
@ -206,6 +206,7 @@ public:
|
|||
int GetLumpFlags (int lump); // Return the flags for this lump
|
||||
void GetLumpName (char *to, int lump) const; // [RH] Copies the lump name to to using uppercopy
|
||||
const char *GetLumpFullName (int lump) const; // [RH] Returns the lump's full name
|
||||
FString GetLumpFullPath (int lump) const; // [RH] Returns wad's name + lump's full name
|
||||
int GetLumpFile (int lump) const; // [RH] Returns wadnum for a specified lump
|
||||
int GetLumpNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to
|
||||
bool CheckLumpName (int lump, const char *name) const; // [RH] Returns true if the names match
|
||||
|
|
|
@ -395,10 +395,10 @@ void WI_LoadBackground(bool isenterpic)
|
|||
}
|
||||
else
|
||||
{
|
||||
int lumpnum=Wads.GetNumForName(lumpname+1);
|
||||
int lumpnum=Wads.CheckNumForFullName(lumpname+1, true);
|
||||
if (lumpnum>=0)
|
||||
{
|
||||
FScanner sc(lumpnum,lumpname+1);
|
||||
FScanner sc(lumpnum);
|
||||
while (sc.GetString())
|
||||
{
|
||||
memset(&an,0,sizeof(an));
|
||||
|
|
|
@ -2,7 +2,7 @@ ifeq (Windows_NT,$(OS))
|
|||
WIN=1
|
||||
WINCMD=1
|
||||
endif
|
||||
ifeq (msys,$(OSTYPE))
|
||||
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||
WIN=1
|
||||
WINCMD=0
|
||||
endif
|
||||
|
|
43
tools/lemon/Makefile
Normal file
43
tools/lemon/Makefile
Normal file
|
@ -0,0 +1,43 @@
|
|||
ifeq (Windows_NT,$(OS))
|
||||
WIN=1
|
||||
WINCMD=1
|
||||
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||
WINCMD=0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (1,$(WIN))
|
||||
EXE = lemon.exe
|
||||
CFLAGS = $(LOC) -D_WIN32 -Os -Wall -Wno-implicit -fomit-frame-pointer
|
||||
else
|
||||
EXE = lemon
|
||||
CFLAGS = -Os -Wall -Wno-implicit -fomit-frame-pointer
|
||||
endif
|
||||
|
||||
CCDV = @../../ccdv
|
||||
CC = gcc
|
||||
LDFLAGS = -s
|
||||
|
||||
OBJS = lemon.o
|
||||
|
||||
all: $(EXE)
|
||||
|
||||
$(EXE): $(OBJS)
|
||||
$(CCDV) $(CC) $(LDFLAGS) -o $(EXE) $(OBJS)
|
||||
|
||||
%.o: %.c
|
||||
$(CCDV) $(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
ifeq (1,$(WINCMD))
|
||||
-del /q /f $(EXE) 2>nul
|
||||
-del /q /f *.o 2>nul
|
||||
else
|
||||
rm -f $(EXE)
|
||||
rm -f *.o
|
||||
endif
|
||||
|
||||
lemon.o: lemon.c lempar.c
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
EXE = lemon.exe
|
||||
|
||||
CCDV = @../../ccdv
|
||||
CC = gcc
|
||||
CFLAGS = $(LOC) -D_WIN32 -Os -Wall -Wno-implicit -fomit-frame-pointer
|
||||
|
||||
OBJS = lemon.o
|
||||
|
||||
all: $(EXE)
|
||||
|
||||
.c.o:
|
||||
$(CCDV) $(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(EXE): $(OBJS)
|
||||
$(CCDV) $(CC) -o $(EXE) $(OBJS)
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
-del /q /f $(EXE) 2>nul
|
||||
-del /q /f *.o 2>nul
|
||||
|
||||
lemon.o: lemon.c lempar.c
|
|
@ -1,10 +1,9 @@
|
|||
ifeq (Windows_NT,$(OS))
|
||||
WIN=1
|
||||
WINCMD=1
|
||||
endif
|
||||
ifeq (msys,$(OSTYPE))
|
||||
WIN=1
|
||||
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||
WINCMD=0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (1,$(WIN))
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
ifeq (Windows_NT,$(OS))
|
||||
WIN=1
|
||||
WINCMD=1
|
||||
endif
|
||||
ifeq (msys,$(OSTYPE))
|
||||
WIN=1
|
||||
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||
WINCMD=0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (1,$(WIN))
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue