mirror of
https://github.com/ZDoom/gzdoom-last-svn.git
synced 2025-06-04 11:10:48 +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
34417
docs/rh-log.txt
34417
docs/rh-log.txt
File diff suppressed because it is too large
Load diff
|
@ -2860,6 +2860,10 @@
|
||||||
RelativePath=".\src\oplsynth\music_opl_mididevice.cpp"
|
RelativePath=".\src\oplsynth\music_opl_mididevice.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\oplsynth\music_opldumper_mididevice.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="src\sound\music_spc.cpp"
|
RelativePath="src\sound\music_spc.cpp"
|
||||||
>
|
>
|
||||||
|
@ -2903,10 +2907,6 @@
|
||||||
RelativePath=".\src\oplsynth\fmopl.h"
|
RelativePath=".\src\oplsynth\fmopl.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\src\oplsynth\mlkernel.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\oplsynth\mlopl.cpp"
|
RelativePath=".\src\oplsynth\mlopl.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -33,7 +33,7 @@ $(STATICLIB): $(OBJS)
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
ifeq (msys,$(OSTYPE))
|
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||||
rm -f $(STATICLIB)
|
rm -f $(STATICLIB)
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
# Makefile for snes_spc, derived from zlib/Makefile.mgw.
|
# Makefile for snes_spc, derived from zlib/Makefile.mgw.
|
||||||
|
|
||||||
|
CMD=0
|
||||||
ifeq (Windows_NT,$(OS))
|
ifeq (Windows_NT,$(OS))
|
||||||
CMD=1
|
CMD=1
|
||||||
endif
|
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||||
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
CMD=0
|
||||||
CMD=0
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
STATICLIB = libsnes_spc.a
|
STATICLIB = libsnes_spc.a
|
||||||
|
|
|
@ -72,7 +72,7 @@ DEFINE_SPECIAL(TeleportOther, 76, 3, 3)
|
||||||
DEFINE_SPECIAL(TeleportGroup, 77, 5, 5)
|
DEFINE_SPECIAL(TeleportGroup, 77, 5, 5)
|
||||||
DEFINE_SPECIAL(TeleportInSector, 78, 4, 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_Suspend, 81, 2, 2)
|
||||||
DEFINE_SPECIAL(ACS_Terminate, 82, 2, 2)
|
DEFINE_SPECIAL(ACS_Terminate, 82, 2, 2)
|
||||||
DEFINE_SPECIAL(ACS_LockedExecute, 83, 5, 5)
|
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_Floor, 223, 4, 4)
|
||||||
DEFINE_SPECIAL(Scroll_Ceiling, 224, 4, 4)
|
DEFINE_SPECIAL(Scroll_Ceiling, 224, 4, 4)
|
||||||
DEFINE_SPECIAL(Scroll_Texture_Offsets, 225, -1, -1)
|
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(PointPush_SetForce, 227, -1, -1)
|
||||||
DEFINE_SPECIAL(Plat_RaiseAndStayTx0, 228, 2, 2)
|
DEFINE_SPECIAL(Plat_RaiseAndStayTx0, 228, 2, 2)
|
||||||
DEFINE_SPECIAL(Thing_SetGoal, 229, 3, 4)
|
DEFINE_SPECIAL(Thing_SetGoal, 229, 3, 4)
|
||||||
|
|
|
@ -299,6 +299,7 @@ enum
|
||||||
MF5_NEVERRESPAWN = 0x00040000, // never respawns, regardless of skill setting
|
MF5_NEVERRESPAWN = 0x00040000, // never respawns, regardless of skill setting
|
||||||
MF5_DONTRIP = 0x00080000, // Ripping projectiles explode when hittin this actor
|
MF5_DONTRIP = 0x00080000, // Ripping projectiles explode when hittin this actor
|
||||||
MF5_NOINFIGHTING = 0x00100000, // This actor doesn't switch target when it's hurt
|
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 ---
|
// --- mobj.renderflags ---
|
||||||
|
|
||||||
|
@ -702,6 +703,7 @@ public:
|
||||||
//Added by MC:
|
//Added by MC:
|
||||||
SDWORD id; // Player ID (for items, # in list.)
|
SDWORD id; // Player ID (for items, # in list.)
|
||||||
|
|
||||||
|
BYTE smokecounter;
|
||||||
BYTE FloatBobPhase;
|
BYTE FloatBobPhase;
|
||||||
BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc)
|
BYTE FriendPlayer; // [RH] Player # + 1 this friendly monster works for (so 0 is no player, 1 is player 0, etc)
|
||||||
DWORD Translation;
|
DWORD Translation;
|
||||||
|
@ -760,6 +762,7 @@ public:
|
||||||
bool SetStateNF (FState *newstate);
|
bool SetStateNF (FState *newstate);
|
||||||
virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true);
|
virtual bool UpdateWaterLevel (fixed_t oldz, bool splash=true);
|
||||||
bool isFast();
|
bool isFast();
|
||||||
|
void SetIdle();
|
||||||
|
|
||||||
FState *FindState (FName label) const;
|
FState *FindState (FName label) const;
|
||||||
FState *FindState (FName label, FName sublabel, bool exact = false) const;
|
FState *FindState (FName label, FName sublabel, bool exact = false) const;
|
||||||
|
|
107
src/am_map.cpp
107
src/am_map.cpp
|
@ -115,8 +115,6 @@ inline fixed_t MTOF(fixed_t x)
|
||||||
return MulScale24 (x, scale_mtof);
|
return MulScale24 (x, scale_mtof);
|
||||||
}
|
}
|
||||||
|
|
||||||
//static int WeightingScale;
|
|
||||||
|
|
||||||
CVAR (Int, am_rotate, 0, CVAR_ARCHIVE);
|
CVAR (Int, am_rotate, 0, CVAR_ARCHIVE);
|
||||||
CVAR (Int, am_overlay, 0, CVAR_ARCHIVE);
|
CVAR (Int, am_overlay, 0, CVAR_ARCHIVE);
|
||||||
CVAR (Bool, am_showsecrets, true, 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_showtime, true, CVAR_ARCHIVE);
|
||||||
CVAR (Bool, am_showtotaltime, false, CVAR_ARCHIVE);
|
CVAR (Bool, am_showtotaltime, false, CVAR_ARCHIVE);
|
||||||
CVAR (Bool, am_usecustomcolors, true, 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_backcolor, 0x6c5440, CVAR_ARCHIVE);
|
||||||
CVAR (Color, am_yourcolor, 0xfce8d8, CVAR_ARCHIVE);
|
CVAR (Color, am_yourcolor, 0xfce8d8, CVAR_ARCHIVE);
|
||||||
CVAR (Color, am_wallcolor, 0x2c1808, 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;
|
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_rotatePoint (fixed_t *x, fixed_t *y);
|
||||||
void AM_rotate (fixed_t *x, fixed_t *y, angle_t an);
|
void AM_rotate (fixed_t *x, fixed_t *y, angle_t an);
|
||||||
void AM_doFollowPlayer ();
|
void AM_doFollowPlayer ();
|
||||||
|
@ -733,57 +720,6 @@ static void AM_initColors (bool overlayed)
|
||||||
NotSeenColor = DoomColors[10];
|
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;
|
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.
|
// Determines visible lines, draws them.
|
||||||
// This is LineDef based, not LineSeg based.
|
// This is LineDef based, not LineSeg based.
|
||||||
|
@ -1384,18 +1336,14 @@ void AM_drawWalls (bool allmap)
|
||||||
if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0)
|
if ((lines[i].flags & ML_DONTDRAW) && am_cheat == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!lines[i].backsector)
|
if (AM_CheckSecret(&lines[i]))
|
||||||
{
|
{
|
||||||
if (lines[i].frontsector->oldspecial &&
|
// map secret sectors like Boom
|
||||||
(am_map_secrets==2 || (am_map_secrets==1 && !(lines[i].frontsector->special&SECRET_MASK))))
|
AM_drawMline(&l, SecretSectorColor);
|
||||||
{
|
}
|
||||||
// map secret sectors like Boom
|
else if (!lines[i].backsector)
|
||||||
AM_drawMline(&l, SecretSectorColor);
|
{
|
||||||
}
|
AM_drawMline(&l, WallColor);
|
||||||
else
|
|
||||||
{
|
|
||||||
AM_drawMline(&l, WallColor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1424,6 +1372,7 @@ void AM_drawWalls (bool allmap)
|
||||||
}
|
}
|
||||||
else if (lines[i].special == Door_LockedRaise ||
|
else if (lines[i].special == Door_LockedRaise ||
|
||||||
lines[i].special == ACS_LockedExecute ||
|
lines[i].special == ACS_LockedExecute ||
|
||||||
|
lines[i].special == ACS_LockedExecuteDoor ||
|
||||||
(lines[i].special == Generic_Door && lines[i].args[4]!=0))
|
(lines[i].special == Generic_Door && lines[i].args[4]!=0))
|
||||||
{
|
{
|
||||||
if (am_usecustomcolors)
|
if (am_usecustomcolors)
|
||||||
|
@ -1805,7 +1754,6 @@ void AM_Drawer ()
|
||||||
f_w = screen->GetWidth ();
|
f_w = screen->GetWidth ();
|
||||||
f_h = ST_Y;
|
f_h = ST_Y;
|
||||||
f_p = screen->GetPitch ();
|
f_p = screen->GetPitch ();
|
||||||
//WeightingScale = 0;
|
|
||||||
|
|
||||||
AM_clearFB(Background);
|
AM_clearFB(Background);
|
||||||
}
|
}
|
||||||
|
@ -1816,13 +1764,6 @@ void AM_Drawer ()
|
||||||
f_w = realviewwidth;
|
f_w = realviewwidth;
|
||||||
f_h = realviewheight;
|
f_h = realviewheight;
|
||||||
f_p = screen->GetPitch ();
|
f_p = screen->GetPitch ();
|
||||||
/*
|
|
||||||
WeightingScale = (int)(am_ovtrans * 256.f);
|
|
||||||
if (WeightingScale < 0 || WeightingScale >= 256)
|
|
||||||
{
|
|
||||||
WeightingScale = 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
AM_activateNewScale();
|
AM_activateNewScale();
|
||||||
|
|
||||||
|
|
|
@ -266,12 +266,10 @@ CCMD (idclev)
|
||||||
// Catch invalid maps.
|
// Catch invalid maps.
|
||||||
mapname = CalcMapName (epsd, map);
|
mapname = CalcMapName (epsd, map);
|
||||||
|
|
||||||
MapData * mapd = P_OpenMapData(mapname);
|
if (!P_CheckMapData(mapname))
|
||||||
if (mapd == NULL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// So be it.
|
// So be it.
|
||||||
delete mapd;
|
|
||||||
Printf ("%s\n", GStrings("STSTR_CLEV"));
|
Printf ("%s\n", GStrings("STSTR_CLEV"));
|
||||||
G_DeferedInitNew (mapname);
|
G_DeferedInitNew (mapname);
|
||||||
players[0].health = 0; // Force reset
|
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.
|
// Just because it's in MAPINFO doesn't mean it's in the wad.
|
||||||
|
|
||||||
MapData * map = P_OpenMapData(mapname);
|
if (P_CheckMapData(mapname))
|
||||||
if (map != NULL)
|
|
||||||
{
|
{
|
||||||
// So be it.
|
// So be it.
|
||||||
delete map;
|
|
||||||
Printf ("%s\n", GStrings("STSTR_CLEV"));
|
Printf ("%s\n", GStrings("STSTR_CLEV"));
|
||||||
G_DeferedInitNew (mapname);
|
G_DeferedInitNew (mapname);
|
||||||
return;
|
return;
|
||||||
|
@ -323,14 +319,12 @@ CCMD (changemap)
|
||||||
|
|
||||||
if (argv.argc() > 1)
|
if (argv.argc() > 1)
|
||||||
{
|
{
|
||||||
MapData * map = P_OpenMapData(argv[1]);
|
if (!P_CheckMapData(argv[1]))
|
||||||
if (map == NULL)
|
|
||||||
{
|
{
|
||||||
Printf ("No map %s\n", argv[1]);
|
Printf ("No map %s\n", argv[1]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete map;
|
|
||||||
if (argv.argc() > 2)
|
if (argv.argc() > 2)
|
||||||
{
|
{
|
||||||
Net_WriteByte (DEM_CHANGEMAP2);
|
Net_WriteByte (DEM_CHANGEMAP2);
|
||||||
|
|
|
@ -2184,8 +2184,15 @@ void DoDehPatch (const char *patchfile, bool autoloading)
|
||||||
if (!PatchFile)
|
if (!PatchFile)
|
||||||
{
|
{
|
||||||
// Couldn't find it on disk, try reading it from a lump
|
// Couldn't find it on disk, try reading it from a lump
|
||||||
FString filebase(ExtractFileBase (patchfile));
|
lump = Wads.CheckNumForFullName(patchfile, true);
|
||||||
lump = Wads.CheckNumForName (filebase);
|
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)
|
if (lump >= 0)
|
||||||
{
|
{
|
||||||
filelen = Wads.LumpLength (lump);
|
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
|
// [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.
|
// and name it TITLEMAP. That map will be loaded and used as the title.
|
||||||
|
|
||||||
MapData * map = P_OpenMapData("TITLEMAP");
|
if (P_CheckMapData("TITLEMAP"))
|
||||||
if (map != NULL)
|
|
||||||
{
|
{
|
||||||
delete map;
|
|
||||||
G_InitNew ("TITLEMAP", true);
|
G_InitNew ("TITLEMAP", true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2281,14 +2279,12 @@ void D_DoomMain (void)
|
||||||
p = Args->CheckParm ("+map");
|
p = Args->CheckParm ("+map");
|
||||||
if (p && p < Args->NumArgs()-1)
|
if (p && p < Args->NumArgs()-1)
|
||||||
{
|
{
|
||||||
MapData * map = P_OpenMapData(Args->GetArg (p+1));
|
if (!P_CheckMapData(Args->GetArg (p+1)))
|
||||||
if (map == NULL)
|
|
||||||
{
|
{
|
||||||
Printf ("Can't find map %s\n", Args->GetArg (p+1));
|
Printf ("Can't find map %s\n", Args->GetArg (p+1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete map;
|
|
||||||
strncpy (startmap, Args->GetArg (p+1), 8);
|
strncpy (startmap, Args->GetArg (p+1), 8);
|
||||||
Args->GetArg (p)[0] = '-';
|
Args->GetArg (p)[0] = '-';
|
||||||
autostart = true;
|
autostart = true;
|
||||||
|
@ -2355,10 +2351,6 @@ void D_DoomMain (void)
|
||||||
StartScreen->AppendStatusLine(temp);
|
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
|
// [RH] Parse through all loaded mapinfo lumps
|
||||||
Printf ("G_ParseMapInfo: Load map definitions.\n");
|
Printf ("G_ParseMapInfo: Load map definitions.\n");
|
||||||
G_ParseMapInfo ();
|
G_ParseMapInfo ();
|
||||||
|
|
|
@ -51,6 +51,7 @@ enum
|
||||||
|
|
||||||
APMETA_DisplayName, // display name (used in menus etc.)
|
APMETA_DisplayName, // display name (used in menus etc.)
|
||||||
APMETA_SoundClass, // sound class
|
APMETA_SoundClass, // sound class
|
||||||
|
APMETA_Face, // doom status bar face (when used)
|
||||||
APMETA_ColorRange, // skin color range
|
APMETA_ColorRange, // skin color range
|
||||||
APMETA_InvulMode,
|
APMETA_InvulMode,
|
||||||
APMETA_HealingRadius,
|
APMETA_HealingRadius,
|
||||||
|
@ -252,6 +253,7 @@ public:
|
||||||
int fixedcolormap; // can be set to REDCOLORMAP, etc.
|
int fixedcolormap; // can be set to REDCOLORMAP, etc.
|
||||||
pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc)
|
pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc)
|
||||||
int morphTics; // player is a chicken/pig if > 0
|
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
|
AWeapon *PremorphWeapon; // ready weapon before morphing
|
||||||
int chickenPeck; // chicken peck countdown
|
int chickenPeck; // chicken peck countdown
|
||||||
int jumpTics; // delay the next jump for a moment
|
int jumpTics; // delay the next jump for a moment
|
||||||
|
|
|
@ -346,7 +346,7 @@ void FDecalLib::ReadAllDecals ()
|
||||||
|
|
||||||
while ((lump = Wads.FindLump ("DECALDEF", &lastlump)) != -1)
|
while ((lump = Wads.FindLump ("DECALDEF", &lastlump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(lump, "DECALDEF");
|
FScanner sc(lump);
|
||||||
ReadDecals (sc);
|
ReadDecals (sc);
|
||||||
}
|
}
|
||||||
// Supporting code to allow specifying decals directly in the DECORATE lump
|
// Supporting code to allow specifying decals directly in the DECORATE lump
|
||||||
|
|
|
@ -149,9 +149,6 @@ extern int viewangleoffset;
|
||||||
extern int consoleplayer;
|
extern int consoleplayer;
|
||||||
|
|
||||||
|
|
||||||
extern level_locals_t level;
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
// DEMO playback/recording related stuff.
|
// DEMO playback/recording related stuff.
|
||||||
// No demo, there is a human player in charge?
|
// No demo, there is a human player in charge?
|
||||||
|
|
|
@ -1314,7 +1314,7 @@ static void GetFinaleText (const char *msgLumpName)
|
||||||
{
|
{
|
||||||
int msgLump;
|
int msgLump;
|
||||||
|
|
||||||
msgLump = Wads.CheckNumForName(msgLumpName);
|
msgLump = Wads.CheckNumForFullName(msgLumpName, true);
|
||||||
if (msgLump != -1)
|
if (msgLump != -1)
|
||||||
{
|
{
|
||||||
char *textbuf;
|
char *textbuf;
|
||||||
|
|
|
@ -9,7 +9,6 @@ class AActor;
|
||||||
|
|
||||||
void T_PreprocessScripts();
|
void T_PreprocessScripts();
|
||||||
void T_LoadScripts(MapData * map);
|
void T_LoadScripts(MapData * map);
|
||||||
void T_PrepareSpawnThing();
|
void T_AddSpawnedThing(AActor * );
|
||||||
void T_RegisterSpawnThing(AActor * );
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -304,31 +304,15 @@ void T_LoadScripts(MapData *map)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Registers an entry in the SpawnedThings table
|
// Adds an actor to the list of spawned things
|
||||||
// If no actor is spawned it will remain NULL, otherwise T_RegisterSpawnThing
|
|
||||||
// will be called to set it
|
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void T_PrepareSpawnThing()
|
void T_AddSpawnedThing(AActor * ac)
|
||||||
{
|
|
||||||
if (DFraggleThinker::ActiveThinker)
|
|
||||||
{
|
|
||||||
DFraggleThinker::ActiveThinker->SpawnedThings.Push(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Sets the last entry in the table to the passed actor
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void T_RegisterSpawnThing(AActor * ac)
|
|
||||||
{
|
{
|
||||||
if (DFraggleThinker::ActiveThinker)
|
if (DFraggleThinker::ActiveThinker)
|
||||||
{
|
{
|
||||||
TArray<TObjPtr<AActor> > &SpawnedThings = DFraggleThinker::ActiveThinker->SpawnedThings;
|
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;
|
DFraggleThinker *th = DFraggleThinker::ActiveThinker;
|
||||||
if (th)
|
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 (arg1 && ln && backSide) return false;
|
||||||
if (arg2!=0 && !P_CheckKeys(it, arg2, !!arg3)) 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
|
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;
|
angle += pr_punch.Random2() << 18;
|
||||||
pitch = P_AimLineAttack (actor, angle, MELEERANGE);
|
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
|
// turn to face target
|
||||||
if (linetarget)
|
if (linetarget)
|
||||||
|
|
|
@ -456,7 +456,7 @@ void A_M_Punch (AActor *self)
|
||||||
A_FaceTarget (self);
|
A_FaceTarget (self);
|
||||||
angle = self->angle + (pr_m_punch.Random2() << 18);
|
angle = self->angle + (pr_m_punch.Random2() << 18);
|
||||||
pitch = P_AimLineAttack (self, angle, MELEERANGE);
|
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
|
// turn to face target
|
||||||
if (linetarget)
|
if (linetarget)
|
||||||
|
@ -486,7 +486,7 @@ void A_M_BerserkPunch (AActor *self)
|
||||||
A_FaceTarget (self);
|
A_FaceTarget (self);
|
||||||
angle = self->angle + (pr_m_punch.Random2() << 18);
|
angle = self->angle + (pr_m_punch.Random2() << 18);
|
||||||
pitch = P_AimLineAttack (self, angle, MELEERANGE);
|
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
|
// turn to face target
|
||||||
if (linetarget)
|
if (linetarget)
|
||||||
|
|
|
@ -2291,11 +2291,11 @@ void G_BeginRecording (const char *startmap)
|
||||||
// G_PlayDemo
|
// G_PlayDemo
|
||||||
//
|
//
|
||||||
|
|
||||||
char defdemoname[128];
|
FString defdemoname;
|
||||||
|
|
||||||
void G_DeferedPlayDemo (char *name)
|
void G_DeferedPlayDemo (char *name)
|
||||||
{
|
{
|
||||||
strncpy (defdemoname, name, 127);
|
defdemoname = name;
|
||||||
gameaction = ga_playdemo;
|
gameaction = ga_playdemo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2457,7 +2457,7 @@ void G_DoPlayDemo (void)
|
||||||
gameaction = ga_nothing;
|
gameaction = ga_nothing;
|
||||||
|
|
||||||
// [RH] Allow for demos not loaded as lumps
|
// [RH] Allow for demos not loaded as lumps
|
||||||
demolump = Wads.CheckNumForName (defdemoname);
|
demolump = Wads.CheckNumForFullName (defdemoname, true);
|
||||||
if (demolump >= 0)
|
if (demolump >= 0)
|
||||||
{
|
{
|
||||||
int demolen = Wads.LumpLength (demolump);
|
int demolen = Wads.LumpLength (demolump);
|
||||||
|
@ -2472,7 +2472,7 @@ void G_DoPlayDemo (void)
|
||||||
}
|
}
|
||||||
demo_p = demobuffer;
|
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
|
C_BackupCVars (); // [RH] Save cvars that might be affected by demo
|
||||||
|
|
||||||
|
@ -2520,7 +2520,7 @@ void G_TimeDemo (char* name)
|
||||||
timingdemo = true;
|
timingdemo = true;
|
||||||
singletics = true;
|
singletics = true;
|
||||||
|
|
||||||
strncpy (defdemoname, name, 128);
|
defdemoname = name;
|
||||||
gameaction = ga_playdemo;
|
gameaction = ga_playdemo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -412,7 +412,7 @@ void A_BeakAttackPL1 (AActor *actor)
|
||||||
damage = 1 + (pr_beakatkpl1()&3);
|
damage = 1 + (pr_beakatkpl1()&3);
|
||||||
angle = player->mo->angle;
|
angle = player->mo->angle;
|
||||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
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)
|
if (linetarget)
|
||||||
{
|
{
|
||||||
player->mo->angle = R_PointToAngle2 (player->mo->x,
|
player->mo->angle = R_PointToAngle2 (player->mo->x,
|
||||||
|
@ -444,7 +444,7 @@ void A_BeakAttackPL2 (AActor *actor)
|
||||||
damage = pr_beakatkpl2.HitDice (4);
|
damage = pr_beakatkpl2.HitDice (4);
|
||||||
angle = player->mo->angle;
|
angle = player->mo->angle;
|
||||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
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)
|
if (linetarget)
|
||||||
{
|
{
|
||||||
player->mo->angle = R_PointToAngle2 (player->mo->x,
|
player->mo->angle = R_PointToAngle2 (player->mo->x,
|
||||||
|
|
|
@ -217,7 +217,7 @@ void A_StaffAttackPL1 (AActor *actor)
|
||||||
angle = player->mo->angle;
|
angle = player->mo->angle;
|
||||||
angle += pr_sap.Random2() << 18;
|
angle += pr_sap.Random2() << 18;
|
||||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
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)
|
if (linetarget)
|
||||||
{
|
{
|
||||||
//S_StartSound(player->mo, sfx_stfhit);
|
//S_StartSound(player->mo, sfx_stfhit);
|
||||||
|
@ -256,7 +256,7 @@ void A_StaffAttackPL2 (AActor *actor)
|
||||||
angle = player->mo->angle;
|
angle = player->mo->angle;
|
||||||
angle += pr_sap2.Random2() << 18;
|
angle += pr_sap2.Random2() << 18;
|
||||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
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)
|
if (linetarget)
|
||||||
{
|
{
|
||||||
//S_StartSound(player->mo, sfx_stfpow);
|
//S_StartSound(player->mo, sfx_stfpow);
|
||||||
|
|
|
@ -94,7 +94,7 @@ void A_CMaceAttack (AActor *actor)
|
||||||
slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE);
|
slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE);
|
||||||
if (linetarget)
|
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);
|
AdjustPlayerAngle (player->mo);
|
||||||
// player->mo->angle = R_PointToAngle2(player->mo->x,
|
// player->mo->angle = R_PointToAngle2(player->mo->x,
|
||||||
// player->mo->y, linetarget->x, linetarget->y);
|
// player->mo->y, linetarget->x, linetarget->y);
|
||||||
|
@ -104,7 +104,7 @@ void A_CMaceAttack (AActor *actor)
|
||||||
slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE);
|
slope = P_AimLineAttack (player->mo, angle, 2*MELEERANGE);
|
||||||
if (linetarget)
|
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);
|
AdjustPlayerAngle (player->mo);
|
||||||
// player->mo->angle = R_PointToAngle2(player->mo->x,
|
// player->mo->angle = R_PointToAngle2(player->mo->x,
|
||||||
// player->mo->y, linetarget->x, linetarget->y);
|
// player->mo->y, linetarget->x, linetarget->y);
|
||||||
|
|
|
@ -352,7 +352,7 @@ void A_FAxeAttack (AActor *actor)
|
||||||
slope = P_AimLineAttack (pmo, angle, AXERANGE);
|
slope = P_AimLineAttack (pmo, angle, AXERANGE);
|
||||||
if (linetarget)
|
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)
|
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||||||
{
|
{
|
||||||
P_ThrustMobj (linetarget, angle, power);
|
P_ThrustMobj (linetarget, angle, power);
|
||||||
|
@ -365,7 +365,7 @@ void A_FAxeAttack (AActor *actor)
|
||||||
slope = P_AimLineAttack (pmo, angle, AXERANGE);
|
slope = P_AimLineAttack (pmo, angle, AXERANGE);
|
||||||
if (linetarget)
|
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)
|
if (linetarget->flags3&MF3_ISMONSTER)
|
||||||
{
|
{
|
||||||
P_ThrustMobj (linetarget, angle, power);
|
P_ThrustMobj (linetarget, angle, power);
|
||||||
|
@ -380,7 +380,7 @@ void A_FAxeAttack (AActor *actor)
|
||||||
|
|
||||||
angle = pmo->angle;
|
angle = pmo->angle;
|
||||||
slope = P_AimLineAttack (pmo, angle, MELEERANGE);
|
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:
|
axedone:
|
||||||
if (useMana == 2)
|
if (useMana == 2)
|
||||||
|
|
|
@ -194,7 +194,7 @@ void A_FHammerAttack (AActor *actor)
|
||||||
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE);
|
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE);
|
||||||
if (linetarget)
|
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);
|
AdjustPlayerAngle(pmo);
|
||||||
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||||||
{
|
{
|
||||||
|
@ -207,7 +207,7 @@ void A_FHammerAttack (AActor *actor)
|
||||||
slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE);
|
slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE);
|
||||||
if(linetarget)
|
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);
|
AdjustPlayerAngle(pmo);
|
||||||
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
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
|
// didn't find any targets in meleerange, so set to throw out a hammer
|
||||||
angle = pmo->angle;
|
angle = pmo->angle;
|
||||||
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE);
|
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;
|
pmo->special1 = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,7 +258,7 @@ void A_FPunchAttack (AActor *actor)
|
||||||
power = 6*FRACUNIT;
|
power = 6*FRACUNIT;
|
||||||
pufftype = RUNTIME_CLASS(AHammerPuff);
|
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)
|
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||||||
{
|
{
|
||||||
P_ThrustMobj (linetarget, angle, power);
|
P_ThrustMobj (linetarget, angle, power);
|
||||||
|
@ -277,7 +277,7 @@ void A_FPunchAttack (AActor *actor)
|
||||||
power = 6*FRACUNIT;
|
power = 6*FRACUNIT;
|
||||||
pufftype = RUNTIME_CLASS(AHammerPuff);
|
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)
|
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||||||
{
|
{
|
||||||
P_ThrustMobj (linetarget, angle, power);
|
P_ThrustMobj (linetarget, angle, power);
|
||||||
|
@ -291,7 +291,7 @@ void A_FPunchAttack (AActor *actor)
|
||||||
|
|
||||||
angle = pmo->angle;
|
angle = pmo->angle;
|
||||||
slope = P_AimLineAttack (pmo, angle, MELEERANGE);
|
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:
|
punchdone:
|
||||||
if (pmo->special1 == 3)
|
if (pmo->special1 == 3)
|
||||||
|
|
|
@ -269,7 +269,7 @@ void A_SnoutAttack (AActor *actor)
|
||||||
damage = 3+(pr_snoutattack()&3);
|
damage = 3+(pr_snoutattack()&3);
|
||||||
angle = player->mo->angle;
|
angle = player->mo->angle;
|
||||||
slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
|
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);
|
S_Sound(player->mo, CHAN_VOICE, "PigActive", 1, ATTN_NORM);
|
||||||
if(linetarget)
|
if(linetarget)
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "m_png.h"
|
#include "m_png.h"
|
||||||
|
#include "gstrings.h"
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -102,7 +103,14 @@ void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs)
|
||||||
}
|
}
|
||||||
if (cluster->clustername)
|
if (cluster->clustername)
|
||||||
{
|
{
|
||||||
strncpy(level.level_name, cluster->clustername, 64);
|
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;
|
level.level_name[63]=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
356
src/g_level.cpp
356
src/g_level.cpp
|
@ -137,7 +137,7 @@ extern const AInventory *SendItemUse, *SendItemDrop;
|
||||||
|
|
||||||
void *statcopy; // for statistics driver
|
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;
|
static TArray<cluster_info_t> wadclusterinfos;
|
||||||
TArray<level_info_t> wadlevelinfos;
|
TArray<level_info_t> wadlevelinfos;
|
||||||
|
@ -180,6 +180,7 @@ static const char *MapInfoTopLevel[] =
|
||||||
"clearepisodes",
|
"clearepisodes",
|
||||||
"skill",
|
"skill",
|
||||||
"clearskills",
|
"clearskills",
|
||||||
|
"adddefaultmap",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,6 +193,7 @@ enum
|
||||||
MITL_CLEAREPISODES,
|
MITL_CLEAREPISODES,
|
||||||
MITL_SKILL,
|
MITL_SKILL,
|
||||||
MITL_CLEARSKILLS,
|
MITL_CLEARSKILLS,
|
||||||
|
MITL_ADDDEFAULTMAP,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *MapInfoMapLevel[] =
|
static const char *MapInfoMapLevel[] =
|
||||||
|
@ -337,7 +339,6 @@ enum EMIType
|
||||||
MITYPE_REDIRECT,
|
MITYPE_REDIRECT,
|
||||||
MITYPE_SPECIALACTION,
|
MITYPE_SPECIALACTION,
|
||||||
MITYPE_COMPATFLAG,
|
MITYPE_COMPATFLAG,
|
||||||
MITYPE_F1, // [RC] F1 help
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MapInfoHandler
|
struct MapInfoHandler
|
||||||
|
@ -414,18 +415,18 @@ MapHandlers[] =
|
||||||
{ MITYPE_CLRFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO },
|
{ MITYPE_CLRFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO },
|
||||||
{ MITYPE_SETFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO },
|
{ MITYPE_SETFLAG, LEVEL_LAXMONSTERACTIVATION, LEVEL_LAXACTIVATIONMAPINFO },
|
||||||
{ MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL},
|
{ MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL},
|
||||||
{ MITYPE_LUMPNAME, lioffset(exitpic), 0 },
|
{ MITYPE_STRING, lioffset(exitpic), 0 },
|
||||||
{ MITYPE_LUMPNAME, lioffset(exitpic), 0 },
|
{ MITYPE_STRING, lioffset(exitpic), 0 },
|
||||||
{ MITYPE_LUMPNAME, lioffset(enterpic), 0 },
|
{ MITYPE_STRING, lioffset(enterpic), 0 },
|
||||||
{ MITYPE_MUSIC, lioffset(intermusic), lioffset(intermusicorder) },
|
{ MITYPE_MUSIC, lioffset(intermusic), lioffset(intermusicorder) },
|
||||||
{ MITYPE_INT, lioffset(airsupply), 0 },
|
{ MITYPE_INT, lioffset(airsupply), 0 },
|
||||||
{ MITYPE_SPECIALACTION, lioffset(specialactions), 0 },
|
{ MITYPE_SPECIALACTION, lioffset(specialactions), 0 },
|
||||||
{ MITYPE_SETFLAG, LEVEL_KEEPFULLINVENTORY, 0 },
|
{ MITYPE_SETFLAG, LEVEL_KEEPFULLINVENTORY, 0 },
|
||||||
{ MITYPE_SETFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
|
{ MITYPE_SETFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
|
||||||
{ MITYPE_CLRFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
|
{ MITYPE_CLRFLAG, LEVEL_MONSTERFALLINGDAMAGE, 0 },
|
||||||
{ MITYPE_LUMPNAME, lioffset(sndseq), 0 },
|
{ MITYPE_STRING, lioffset(sndseq), 0 },
|
||||||
{ MITYPE_LUMPNAME, lioffset(soundinfo), 0 },
|
{ MITYPE_STRING, lioffset(soundinfo), 0 },
|
||||||
{ MITYPE_LUMPNAME, lioffset(soundinfo), 0 },
|
{ MITYPE_STRING, lioffset(soundinfo), 0 },
|
||||||
{ MITYPE_SETFLAG, LEVEL_CLIPMIDTEX, 0 },
|
{ MITYPE_SETFLAG, LEVEL_CLIPMIDTEX, 0 },
|
||||||
{ MITYPE_SETFLAG, LEVEL_WRAPMIDTEX, 0 },
|
{ MITYPE_SETFLAG, LEVEL_WRAPMIDTEX, 0 },
|
||||||
{ MITYPE_CLRFLAG, LEVEL_CROUCH_NO, 0 },
|
{ MITYPE_CLRFLAG, LEVEL_CROUCH_NO, 0 },
|
||||||
|
@ -446,7 +447,7 @@ MapHandlers[] =
|
||||||
{ MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL},
|
{ MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL},
|
||||||
{ MITYPE_COMPATFLAG, COMPATF_INVISIBILITY},
|
{ MITYPE_COMPATFLAG, COMPATF_INVISIBILITY},
|
||||||
{ MITYPE_LUMPNAME, lioffset(bordertexture), 0 },
|
{ MITYPE_LUMPNAME, lioffset(bordertexture), 0 },
|
||||||
{ MITYPE_F1, lioffset(f1), 0, },
|
{ MITYPE_LUMPNAME, lioffset(f1), 0, },
|
||||||
{ MITYPE_SCFLAGS, LEVEL_NOINFIGHTING, ~LEVEL_TOTALINFIGHTING },
|
{ MITYPE_SCFLAGS, LEVEL_NOINFIGHTING, ~LEVEL_TOTALINFIGHTING },
|
||||||
{ MITYPE_SCFLAGS, 0, ~(LEVEL_NOINFIGHTING|LEVEL_TOTALINFIGHTING)},
|
{ MITYPE_SCFLAGS, 0, ~(LEVEL_NOINFIGHTING|LEVEL_TOTALINFIGHTING)},
|
||||||
{ MITYPE_SCFLAGS, LEVEL_TOTALINFIGHTING, ~LEVEL_NOINFIGHTING },
|
{ MITYPE_SCFLAGS, LEVEL_TOTALINFIGHTING, ~LEVEL_NOINFIGHTING },
|
||||||
|
@ -493,7 +494,7 @@ MapInfoHandler ClusterHandlers[] =
|
||||||
{ MITYPE_HEX, cioffset(cdid), 0 },
|
{ MITYPE_HEX, cioffset(cdid), 0 },
|
||||||
{ MITYPE_SETFLAG, CLUSTER_ENTERTEXTINLUMP, 0 },
|
{ MITYPE_SETFLAG, CLUSTER_ENTERTEXTINLUMP, 0 },
|
||||||
{ MITYPE_SETFLAG, CLUSTER_EXITTEXTINLUMP, 0 },
|
{ MITYPE_SETFLAG, CLUSTER_EXITTEXTINLUMP, 0 },
|
||||||
{ MITYPE_STRING, cioffset(clustername), 0 },
|
{ MITYPE_STRING, cioffset(clustername), CLUSTER_LOOKUPNAME },
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ParseMapInfoLower (FScanner &sc,
|
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.
|
// For maps without a BEHAVIOR, this will be cleared.
|
||||||
levelinfo->flags |= LEVEL_LAXMONSTERACTIVATION;
|
levelinfo->flags |= LEVEL_LAXMONSTERACTIVATION;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
levelinfo->flags |= LEVEL_MONSTERFALLINGDAMAGE;
|
|
||||||
}
|
|
||||||
levelinfo->airsupply = 10;
|
levelinfo->airsupply = 10;
|
||||||
|
|
||||||
// new
|
// new
|
||||||
|
@ -627,6 +624,48 @@ static FSpecialAction *CopySpecialActions(FSpecialAction *spec)
|
||||||
return 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)
|
static void G_DoParseMapInfo (int lump)
|
||||||
{
|
{
|
||||||
level_info_t defaultinfo;
|
level_info_t defaultinfo;
|
||||||
|
@ -636,7 +675,7 @@ static void G_DoParseMapInfo (int lump)
|
||||||
int clusterindex;
|
int clusterindex;
|
||||||
QWORD levelflags;
|
QWORD levelflags;
|
||||||
|
|
||||||
FScanner sc(lump, Wads.GetLumpFullName(lump));
|
FScanner sc(lump);
|
||||||
|
|
||||||
SetLevelDefaults (&defaultinfo);
|
SetLevelDefaults (&defaultinfo);
|
||||||
HexenHack = false;
|
HexenHack = false;
|
||||||
|
@ -651,6 +690,11 @@ static void G_DoParseMapInfo (int lump)
|
||||||
ParseMapInfoLower (sc, MapHandlers, MapInfoMapLevel, &defaultinfo, NULL, defaultinfo.flags);
|
ParseMapInfoLower (sc, MapHandlers, MapInfoMapLevel, &defaultinfo, NULL, defaultinfo.flags);
|
||||||
break;
|
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>
|
case MITL_MAP: // map <MAPNAME> <Nice Name>
|
||||||
levelflags = defaultinfo.flags;
|
levelflags = defaultinfo.flags;
|
||||||
sc.MustGetString ();
|
sc.MustGetString ();
|
||||||
|
@ -668,7 +712,8 @@ static void G_DoParseMapInfo (int lump)
|
||||||
| LEVEL_FALLDMG_HX
|
| LEVEL_FALLDMG_HX
|
||||||
| LEVEL_ACTOWNSPECIAL
|
| LEVEL_ACTOWNSPECIAL
|
||||||
| LEVEL_MISSILESACTIVATEIMPACT
|
| LEVEL_MISSILESACTIVATEIMPACT
|
||||||
| LEVEL_INFINITE_FLIGHT;
|
| LEVEL_INFINITE_FLIGHT
|
||||||
|
| LEVEL_MONSTERFALLINGDAMAGE;
|
||||||
}
|
}
|
||||||
levelindex = FindWadLevelInfo (sc.String);
|
levelindex = FindWadLevelInfo (sc.String);
|
||||||
if (levelindex == -1)
|
if (levelindex == -1)
|
||||||
|
@ -681,18 +726,13 @@ static void G_DoParseMapInfo (int lump)
|
||||||
}
|
}
|
||||||
levelinfo = &wadlevelinfos[levelindex];
|
levelinfo = &wadlevelinfos[levelindex];
|
||||||
memcpy (levelinfo, &defaultinfo, sizeof(*levelinfo));
|
memcpy (levelinfo, &defaultinfo, sizeof(*levelinfo));
|
||||||
if (levelinfo->music != NULL)
|
CopyString(levelinfo->music);
|
||||||
{
|
CopyString(levelinfo->intermusic);
|
||||||
levelinfo->music = copystring (levelinfo->music);
|
CopyString(levelinfo->translator);
|
||||||
}
|
CopyString(levelinfo->enterpic);
|
||||||
if (levelinfo->intermusic != NULL)
|
CopyString(levelinfo->exitpic);
|
||||||
{
|
CopyString(levelinfo->soundinfo);
|
||||||
levelinfo->intermusic = copystring (levelinfo->intermusic);
|
CopyString(levelinfo->sndseq);
|
||||||
}
|
|
||||||
if (levelinfo->translator != NULL)
|
|
||||||
{
|
|
||||||
levelinfo->translator = copystring (levelinfo->translator);
|
|
||||||
}
|
|
||||||
levelinfo->specialactions = CopySpecialActions(levelinfo->specialactions);
|
levelinfo->specialactions = CopySpecialActions(levelinfo->specialactions);
|
||||||
if (HexenHack)
|
if (HexenHack)
|
||||||
{
|
{
|
||||||
|
@ -700,14 +740,19 @@ static void G_DoParseMapInfo (int lump)
|
||||||
}
|
}
|
||||||
uppercopy (levelinfo->mapname, sc.String);
|
uppercopy (levelinfo->mapname, sc.String);
|
||||||
sc.MustGetString ();
|
sc.MustGetString ();
|
||||||
if (sc.Compare ("lookup"))
|
if (sc.String[0] == '$')
|
||||||
{
|
{
|
||||||
sc.MustGetString ();
|
// For consistency with other definitions allow $Stringtablename here, too.
|
||||||
ReplaceString (&levelinfo->level_name, sc.String);
|
|
||||||
levelflags |= LEVEL_LOOKUPLEVELNAME;
|
levelflags |= LEVEL_LOOKUPLEVELNAME;
|
||||||
|
ReplaceString (&levelinfo->level_name, sc.String+1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (sc.Compare ("lookup"))
|
||||||
|
{
|
||||||
|
sc.MustGetString ();
|
||||||
|
levelflags |= LEVEL_LOOKUPLEVELNAME;
|
||||||
|
}
|
||||||
ReplaceString (&levelinfo->level_name, sc.String);
|
ReplaceString (&levelinfo->level_name, sc.String);
|
||||||
}
|
}
|
||||||
// Set up levelnum now so that you can use Teleport_NewMap specials
|
// 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);
|
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.
|
SetLevelNum (levelinfo, levelinfo->levelnum); // Wipe out matching levelnums from other maps.
|
||||||
if (levelinfo->pname[0] != 0)
|
if (levelinfo->pname[0] != 0)
|
||||||
{
|
{
|
||||||
|
@ -759,22 +800,7 @@ static void G_DoParseMapInfo (int lump)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clusterinfo = &wadclusterinfos[clusterindex];
|
clusterinfo = &wadclusterinfos[clusterindex];
|
||||||
if (clusterinfo->entertext != NULL)
|
ClearClusterInfoStrings(clusterinfo);
|
||||||
{
|
|
||||||
delete[] clusterinfo->entertext;
|
|
||||||
}
|
|
||||||
if (clusterinfo->exittext != NULL)
|
|
||||||
{
|
|
||||||
delete[] clusterinfo->exittext;
|
|
||||||
}
|
|
||||||
if (clusterinfo->messagemusic != NULL)
|
|
||||||
{
|
|
||||||
delete[] clusterinfo->messagemusic;
|
|
||||||
}
|
|
||||||
if (clusterinfo->clustername != NULL)
|
|
||||||
{
|
|
||||||
delete[] clusterinfo->clustername;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
memset (clusterinfo, 0, sizeof(cluster_info_t));
|
memset (clusterinfo, 0, sizeof(cluster_info_t));
|
||||||
clusterinfo->cluster = sc.Number;
|
clusterinfo->cluster = sc.Number;
|
||||||
|
@ -802,60 +828,6 @@ static void G_DoParseMapInfo (int lump)
|
||||||
ClearLevelInfoStrings(&defaultinfo);
|
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()
|
static void ClearEpisodes()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < EpiDef.numitems; ++i)
|
for (int i = 0; i < EpiDef.numitems; ++i)
|
||||||
|
@ -920,13 +892,6 @@ static void ParseMapInfoLower (FScanner &sc,
|
||||||
case MITYPE_REDIRECT:
|
case MITYPE_REDIRECT:
|
||||||
sc.MustGetString ();
|
sc.MustGetString ();
|
||||||
levelinfo->RedirectType = sc.String;
|
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
|
// Intentional fall-through
|
||||||
|
|
||||||
case MITYPE_MAPNAME: {
|
case MITYPE_MAPNAME: {
|
||||||
|
@ -1064,7 +1029,7 @@ static void ParseMapInfoLower (FScanner &sc,
|
||||||
clusterinfo = &wadclusterinfos[clusterindex];
|
clusterinfo = &wadclusterinfos[clusterindex];
|
||||||
memset (clusterinfo, 0, sizeof(cluster_info_t));
|
memset (clusterinfo, 0, sizeof(cluster_info_t));
|
||||||
clusterinfo->cluster = sc.Number;
|
clusterinfo->cluster = sc.Number;
|
||||||
if (gameinfo.gametype == GAME_Hexen)
|
if (HexenHack)
|
||||||
{
|
{
|
||||||
clusterinfo->flags |= CLUSTER_HUB;
|
clusterinfo->flags |= CLUSTER_HUB;
|
||||||
}
|
}
|
||||||
|
@ -1073,21 +1038,18 @@ static void ParseMapInfoLower (FScanner &sc,
|
||||||
|
|
||||||
case MITYPE_STRING:
|
case MITYPE_STRING:
|
||||||
sc.MustGetString ();
|
sc.MustGetString ();
|
||||||
if (sc.Compare ("lookup"))
|
if (sc.String[0] == '$')
|
||||||
{
|
{
|
||||||
|
// For consistency with other definitions allow $Stringtablename here, too.
|
||||||
flags |= handler->data2;
|
flags |= handler->data2;
|
||||||
sc.MustGetString ();
|
ReplaceString ((char **)(info + handler->data1), sc.String+1);
|
||||||
}
|
}
|
||||||
ReplaceString ((char **)(info + handler->data1), sc.String);
|
else
|
||||||
break;
|
|
||||||
|
|
||||||
case MITYPE_F1:
|
|
||||||
sc.MustGetString ();
|
|
||||||
{
|
{
|
||||||
char *colon = strchr (sc.String, ':');
|
if (sc.Compare ("lookup"))
|
||||||
if (colon)
|
|
||||||
{
|
{
|
||||||
*colon = 0;
|
flags |= handler->data2;
|
||||||
|
sc.MustGetString ();
|
||||||
}
|
}
|
||||||
ReplaceString ((char **)(info + handler->data1), sc.String);
|
ReplaceString ((char **)(info + handler->data1), sc.String);
|
||||||
}
|
}
|
||||||
|
@ -1194,6 +1156,7 @@ static void ParseEpisodeInfo (FScanner &sc)
|
||||||
bool remove = false;
|
bool remove = false;
|
||||||
char key = 0;
|
char key = 0;
|
||||||
bool noskill = false;
|
bool noskill = false;
|
||||||
|
bool optional = false;
|
||||||
|
|
||||||
// Get map name
|
// Get map name
|
||||||
sc.MustGetString ();
|
sc.MustGetString ();
|
||||||
|
@ -1212,7 +1175,12 @@ static void ParseEpisodeInfo (FScanner &sc)
|
||||||
}
|
}
|
||||||
do
|
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 ();
|
sc.MustGetString ();
|
||||||
ReplaceString (&pic, sc.String);
|
ReplaceString (&pic, sc.String);
|
||||||
|
@ -1245,6 +1213,17 @@ static void ParseEpisodeInfo (FScanner &sc)
|
||||||
}
|
}
|
||||||
while (sc.GetString ());
|
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)
|
for (i = 0; i < EpiDef.numitems; ++i)
|
||||||
{
|
{
|
||||||
if (strncmp (EpisodeMaps[i], map, 8) == 0)
|
if (strncmp (EpisodeMaps[i], map, 8) == 0)
|
||||||
|
@ -1412,8 +1391,8 @@ void P_RemoveDefereds (void)
|
||||||
|
|
||||||
bool CheckWarpTransMap (char mapname[9], bool substitute)
|
bool CheckWarpTransMap (char mapname[9], bool substitute)
|
||||||
{
|
{
|
||||||
if (mapname[0] == '&' && mapname[1] == 'w' &&
|
if (mapname[0] == '&' && (mapname[1]&223) == 'W' &&
|
||||||
mapname[2] == 't' && mapname[3] == '@')
|
(mapname[2]&223) == 'T' && mapname[3] == '@')
|
||||||
{
|
{
|
||||||
level_info_t *lev = FindLevelByWarpTrans (atoi (mapname + 4));
|
level_info_t *lev = FindLevelByWarpTrans (atoi (mapname + 4));
|
||||||
if (lev != NULL)
|
if (lev != NULL)
|
||||||
|
@ -1461,12 +1440,12 @@ CCMD (map)
|
||||||
}
|
}
|
||||||
if (argv.argc() > 1)
|
if (argv.argc() > 1)
|
||||||
{
|
{
|
||||||
MapData * map = P_OpenMapData(argv[1]);
|
if (!P_CheckMapData(argv[1]))
|
||||||
if (map == NULL)
|
{
|
||||||
Printf ("No map %s\n", argv[1]);
|
Printf ("No map %s\n", argv[1]);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete map;
|
|
||||||
G_DeferedInitNew (argv[1]);
|
G_DeferedInitNew (argv[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1486,12 +1465,12 @@ CCMD (open)
|
||||||
if (argv.argc() > 1)
|
if (argv.argc() > 1)
|
||||||
{
|
{
|
||||||
sprintf(d_mapname, "file:%s", argv[1]);
|
sprintf(d_mapname, "file:%s", argv[1]);
|
||||||
MapData * map = P_OpenMapData(d_mapname);
|
if (!P_CheckMapData(d_mapname))
|
||||||
if (map == NULL)
|
{
|
||||||
Printf ("No map %s\n", d_mapname);
|
Printf ("No map %s\n", d_mapname);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete map;
|
|
||||||
gameaction = ga_newgame2;
|
gameaction = ga_newgame2;
|
||||||
d_skill = -1;
|
d_skill = -1;
|
||||||
}
|
}
|
||||||
|
@ -1642,12 +1621,10 @@ void G_InitNew (const char *mapname, bool bTitleLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] If this map doesn't exist, bomb out
|
// [RH] If this map doesn't exist, bomb out
|
||||||
MapData * map = P_OpenMapData(mapname);
|
if (!P_CheckMapData(mapname))
|
||||||
if (!map)
|
|
||||||
{
|
{
|
||||||
I_Error ("Could not find map %s\n", mapname);
|
I_Error ("Could not find map %s\n", mapname);
|
||||||
}
|
}
|
||||||
delete map;
|
|
||||||
|
|
||||||
oldSpeed = GameSpeed;
|
oldSpeed = GameSpeed;
|
||||||
wantFast = !!G_SkillProperty(SKILLP_FastMonsters);
|
wantFast = !!G_SkillProperty(SKILLP_FastMonsters);
|
||||||
|
@ -1819,10 +1796,8 @@ const char *G_GetSecretExitMap()
|
||||||
|
|
||||||
if (level.secretmap[0] != 0)
|
if (level.secretmap[0] != 0)
|
||||||
{
|
{
|
||||||
MapData *map = P_OpenMapData(level.secretmap);
|
if (P_CheckMapData(level.secretmap))
|
||||||
if (map != NULL)
|
|
||||||
{
|
{
|
||||||
delete map;
|
|
||||||
nextmap = level.secretmap;
|
nextmap = level.secretmap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2067,7 +2042,7 @@ void G_DoLoadLevel (int position, bool autosave)
|
||||||
|
|
||||||
// DOOM determines the sky texture to be used
|
// DOOM determines the sky texture to be used
|
||||||
// depending on the current episode and the game version.
|
// 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);
|
sky1texture = TexMan.GetTexture (level.skypic1, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable);
|
||||||
sky2texture = TexMan.GetTexture (level.skypic2, 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
|
// The player being spawned here is a short lived dummy and
|
||||||
// must not start any ENTER script or big problems will happen.
|
// must not start any ENTER script or big problems will happen.
|
||||||
P_SpawnPlayer (&playerstarts[pawn->player - players], true);
|
pawndup = P_SpawnPlayer (&playerstarts[pawn->player - players], true);
|
||||||
|
|
||||||
pawndup = pawn->player->mo;
|
|
||||||
if (!startkeepfacing)
|
if (!startkeepfacing)
|
||||||
{
|
{
|
||||||
pawn->angle = pawndup->angle;
|
pawn->angle = pawndup->angle;
|
||||||
|
@ -2431,7 +2404,6 @@ void G_InitLevelLocals ()
|
||||||
level.levelnum = info->levelnum;
|
level.levelnum = info->levelnum;
|
||||||
level.music = info->music;
|
level.music = info->music;
|
||||||
level.musicorder = info->musicorder;
|
level.musicorder = info->musicorder;
|
||||||
level.f1 = info->f1; // [RC] And import the f1 name
|
|
||||||
|
|
||||||
strncpy (level.level_name, info->level_name, 63);
|
strncpy (level.level_name, info->level_name, 63);
|
||||||
G_MaybeLookupLevelName (NULL);
|
G_MaybeLookupLevelName (NULL);
|
||||||
|
@ -2467,7 +2439,7 @@ void G_InitLevelLocals ()
|
||||||
gl_SetFogParams(info->fogdensity, info->outsidefog, info->outsidefogdensity, info->skyfog);
|
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)
|
if (dmflags & DF_NO_JUMP)
|
||||||
return false;
|
return false;
|
||||||
|
@ -2476,7 +2448,7 @@ bool level_locals_s::IsJumpingAllowed() const
|
||||||
return !(level.flags & LEVEL_JUMP_NO);
|
return !(level.flags & LEVEL_JUMP_NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool level_locals_s::IsCrouchingAllowed() const
|
bool FLevelLocals::IsCrouchingAllowed() const
|
||||||
{
|
{
|
||||||
if (dmflags & DF_NO_CROUCH)
|
if (dmflags & DF_NO_CROUCH)
|
||||||
return false;
|
return false;
|
||||||
|
@ -2485,7 +2457,7 @@ bool level_locals_s::IsCrouchingAllowed() const
|
||||||
return !(level.flags & LEVEL_CROUCH_NO);
|
return !(level.flags & LEVEL_CROUCH_NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool level_locals_s::IsFreelookAllowed() const
|
bool FLevelLocals::IsFreelookAllowed() const
|
||||||
{
|
{
|
||||||
if (level.flags & LEVEL_FREELOOK_NO)
|
if (level.flags & LEVEL_FREELOOK_NO)
|
||||||
return false;
|
return false;
|
||||||
|
@ -2544,10 +2516,8 @@ level_info_t *CheckLevelRedirect (level_info_t *info)
|
||||||
if (playeringame[i] && players[i].mo->FindInventory (type))
|
if (playeringame[i] && players[i].mo->FindInventory (type))
|
||||||
{
|
{
|
||||||
// check for actual presence of the map.
|
// check for actual presence of the map.
|
||||||
MapData * map = P_OpenMapData(info->RedirectMap);
|
if (P_CheckMapData(info->RedirectMap))
|
||||||
if (map != NULL)
|
|
||||||
{
|
{
|
||||||
delete map;
|
|
||||||
return FindLevelInfo(info->RedirectMap);
|
return FindLevelInfo(info->RedirectMap);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2634,90 +2604,6 @@ const char *G_MaybeLookupLevelName (level_info_t *ininfo)
|
||||||
return info != NULL ? info->level_name : NULL;
|
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 ()
|
void G_AirControlChanged ()
|
||||||
{
|
{
|
||||||
if (level.aircontrol <= 256)
|
if (level.aircontrol <= 256)
|
||||||
|
@ -3166,7 +3052,7 @@ void P_ReadACSDefereds (PNGHandle *png)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void level_locals_s::Tick ()
|
void FLevelLocals::Tick ()
|
||||||
{
|
{
|
||||||
// Reset carry sectors
|
// Reset carry sectors
|
||||||
if (Scrolls != NULL)
|
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)
|
if (secnum < 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -130,7 +130,7 @@ struct FSpecialAction
|
||||||
FSpecialAction *Next;
|
FSpecialAction *Next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct level_info_s
|
struct level_info_t
|
||||||
{
|
{
|
||||||
char mapname[9];
|
char mapname[9];
|
||||||
int levelnum;
|
int levelnum;
|
||||||
|
@ -146,7 +146,7 @@ struct level_info_s
|
||||||
char *level_name;
|
char *level_name;
|
||||||
char fadetable[9];
|
char fadetable[9];
|
||||||
SBYTE WallVertLight, WallHorizLight;
|
SBYTE WallVertLight, WallHorizLight;
|
||||||
const char *f1;
|
char f1[9];
|
||||||
// TheDefaultLevelInfo initializes everything above this line.
|
// TheDefaultLevelInfo initializes everything above this line.
|
||||||
int musicorder;
|
int musicorder;
|
||||||
FCompressedMemFile *snapshot;
|
FCompressedMemFile *snapshot;
|
||||||
|
@ -172,13 +172,13 @@ struct level_info_s
|
||||||
FName RedirectType;
|
FName RedirectType;
|
||||||
char RedirectMap[9];
|
char RedirectMap[9];
|
||||||
|
|
||||||
char enterpic[9];
|
char *enterpic;
|
||||||
char exitpic[9];
|
char *exitpic;
|
||||||
char *intermusic;
|
char *intermusic;
|
||||||
int intermusicorder;
|
int intermusicorder;
|
||||||
|
|
||||||
char soundinfo[9];
|
char *soundinfo;
|
||||||
char sndseq[9];
|
char *sndseq;
|
||||||
char bordertexture[9];
|
char bordertexture[9];
|
||||||
|
|
||||||
int fogdensity;
|
int fogdensity;
|
||||||
|
@ -187,8 +187,8 @@ struct level_info_s
|
||||||
FSpecialAction * specialactions;
|
FSpecialAction * specialactions;
|
||||||
|
|
||||||
float teamdamage;
|
float teamdamage;
|
||||||
|
|
||||||
};
|
};
|
||||||
typedef struct level_info_s level_info_t;
|
|
||||||
|
|
||||||
// [RH] These get zeroed every tic and are updated by thinkers.
|
// [RH] These get zeroed every tic and are updated by thinkers.
|
||||||
struct FSectorScrollValues
|
struct FSectorScrollValues
|
||||||
|
@ -196,7 +196,7 @@ struct FSectorScrollValues
|
||||||
fixed_t ScrollX, ScrollY;
|
fixed_t ScrollX, ScrollY;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct level_locals_s
|
struct FLevelLocals
|
||||||
{
|
{
|
||||||
void Tick ();
|
void Tick ();
|
||||||
void AddScroller (DScroller *, int secnum);
|
void AddScroller (DScroller *, int secnum);
|
||||||
|
@ -254,15 +254,12 @@ struct level_locals_s
|
||||||
|
|
||||||
bool FromSnapshot; // The current map was restored from a snapshot
|
bool FromSnapshot; // The current map was restored from a snapshot
|
||||||
|
|
||||||
const char *f1;
|
|
||||||
|
|
||||||
float teamdamage;
|
float teamdamage;
|
||||||
|
|
||||||
bool IsJumpingAllowed() const;
|
bool IsJumpingAllowed() const;
|
||||||
bool IsCrouchingAllowed() const;
|
bool IsCrouchingAllowed() const;
|
||||||
bool IsFreelookAllowed() const;
|
bool IsFreelookAllowed() const;
|
||||||
};
|
};
|
||||||
typedef struct level_locals_s level_locals_t;
|
|
||||||
|
|
||||||
enum EndTypes
|
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_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_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_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;
|
extern TArray<level_info_t> wadlevelinfos;
|
||||||
|
|
||||||
|
@ -360,7 +358,6 @@ void G_InitLevelLocals (void);
|
||||||
|
|
||||||
void G_AirControlChanged ();
|
void G_AirControlChanged ();
|
||||||
|
|
||||||
void G_MakeEpisodes (void);
|
|
||||||
const char *G_MaybeLookupLevelName (level_info_t *level);
|
const char *G_MaybeLookupLevelName (level_info_t *level);
|
||||||
|
|
||||||
cluster_info_t *FindClusterInfo (int cluster);
|
cluster_info_t *FindClusterInfo (int cluster);
|
||||||
|
|
|
@ -344,7 +344,7 @@ void P_InitKeyMessages()
|
||||||
ClearLocks();
|
ClearLocks();
|
||||||
while ((lump = Wads.FindLump ("LOCKDEFS", &lastlump)) != -1)
|
while ((lump = Wads.FindLump ("LOCKDEFS", &lastlump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(lump, "LOCKDEFS");
|
FScanner sc(lump);
|
||||||
while (sc.GetString ())
|
while (sc.GetString ())
|
||||||
{
|
{
|
||||||
if (sc.Compare("LOCK"))
|
if (sc.Compare("LOCK"))
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
#include "m_random.h"
|
#include "m_random.h"
|
||||||
#include "a_sharedglobal.h"
|
#include "a_sharedglobal.h"
|
||||||
|
#include "sbar.h"
|
||||||
|
|
||||||
#define MORPHTICS (40*TICRATE)
|
#define MORPHTICS (40*TICRATE)
|
||||||
|
|
||||||
|
@ -56,6 +57,10 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (spawntype == p->mo->GetClass())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
morphed = static_cast<APlayerPawn *>(Spawn (spawntype, actor->x, actor->y, actor->z, NO_REPLACE));
|
morphed = static_cast<APlayerPawn *>(Spawn (spawntype, actor->x, actor->y, actor->z, NO_REPLACE));
|
||||||
DObject::StaticPointerSubstitution (actor, morphed);
|
DObject::StaticPointerSubstitution (actor, morphed);
|
||||||
|
@ -78,6 +83,18 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
|
||||||
actor->flags |= MF_UNMORPHED;
|
actor->flags |= MF_UNMORPHED;
|
||||||
actor->renderflags |= RF_INVISIBLE;
|
actor->renderflags |= RF_INVISIBLE;
|
||||||
p->morphTics = MORPHTICS;
|
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->health = morphed->health;
|
||||||
p->mo = morphed;
|
p->mo = morphed;
|
||||||
p->momx = p->momy = 0;
|
p->momx = p->momy = 0;
|
||||||
|
@ -116,6 +133,18 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype)
|
||||||
p->camera = morphed;
|
p->camera = morphed;
|
||||||
}
|
}
|
||||||
morphed->ScoreIcon = actor->ScoreIcon; // [GRB]
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +211,39 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
||||||
{
|
{
|
||||||
player->camera = mo;
|
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;
|
angle = mo->angle >> ANGLETOFINESHIFT;
|
||||||
Spawn<ATeleportFog> (pmo->x + 20*finecosine[angle],
|
Spawn<ATeleportFog> (pmo->x + 20*finecosine[angle],
|
||||||
pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE);
|
pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE);
|
||||||
|
|
|
@ -183,22 +183,24 @@ enum //drawimage flags
|
||||||
|
|
||||||
enum //drawnumber flags
|
enum //drawnumber flags
|
||||||
{
|
{
|
||||||
DRAWNUMBER_HEALTH = 1,
|
DRAWNUMBER_HEALTH = 0x1,
|
||||||
DRAWNUMBER_ARMOR = 2,
|
DRAWNUMBER_ARMOR = 0x2,
|
||||||
DRAWNUMBER_AMMO1 = 4,
|
DRAWNUMBER_AMMO1 = 0x4,
|
||||||
DRAWNUMBER_AMMO2 = 8,
|
DRAWNUMBER_AMMO2 = 0x8,
|
||||||
DRAWNUMBER_AMMO = 16,
|
DRAWNUMBER_AMMO = 0x10,
|
||||||
DRAWNUMBER_AMMOCAPACITY = 32,
|
DRAWNUMBER_AMMOCAPACITY = 0x20,
|
||||||
DRAWNUMBER_FRAGS = 64,
|
DRAWNUMBER_FRAGS = 0x40,
|
||||||
DRAWNUMBER_INVENTORY = 128,
|
DRAWNUMBER_INVENTORY = 0x80,
|
||||||
DRAWNUMBER_KILLS = 256,
|
DRAWNUMBER_KILLS = 0x100,
|
||||||
DRAWNUMBER_MONSTERS = 512,
|
DRAWNUMBER_MONSTERS = 0x200,
|
||||||
DRAWNUMBER_ITEMS = 1024,
|
DRAWNUMBER_ITEMS = 0x400,
|
||||||
DRAWNUMBER_TOTALITEMS = 2048,
|
DRAWNUMBER_TOTALITEMS = 0x800,
|
||||||
DRAWNUMBER_SECRETS = 4096,
|
DRAWNUMBER_SECRETS = 0x1000,
|
||||||
DRAWNUMBER_TOTALSECRETS = 8192,
|
DRAWNUMBER_TOTALSECRETS = 0x2000,
|
||||||
DRAWNUMBER_ARMORCLASS = 16384,
|
DRAWNUMBER_ARMORCLASS = 0x4000,
|
||||||
DRAWNUMBER_GLOBALVAR = 32768,
|
DRAWNUMBER_GLOBALVAR = 0x8000,
|
||||||
|
DRAWNUMBER_GLOBALARRAY = 0x10000,
|
||||||
|
DRAWNUMBER_FILLZEROS = 0x20000,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum //drawbar flags (will go into special2)
|
enum //drawbar flags (will go into special2)
|
||||||
|
@ -305,6 +307,7 @@ enum //Bar key words
|
||||||
SBARINFO_GAMEMODE,
|
SBARINFO_GAMEMODE,
|
||||||
SBARINFO_PLAYERCLASS,
|
SBARINFO_PLAYERCLASS,
|
||||||
SBARINFO_ASPECTRATIO,
|
SBARINFO_ASPECTRATIO,
|
||||||
|
SBARINFO_ISSELECTED,
|
||||||
SBARINFO_WEAPONAMMO,
|
SBARINFO_WEAPONAMMO,
|
||||||
SBARINFO_ININVENTORY,
|
SBARINFO_ININVENTORY,
|
||||||
};
|
};
|
||||||
|
@ -338,9 +341,9 @@ public:
|
||||||
void SetMugShotState(const char* stateName, bool waitTillDone=false);
|
void SetMugShotState(const char* stateName, bool waitTillDone=false);
|
||||||
private:
|
private:
|
||||||
void doCommands(SBarInfoBlock &block);
|
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 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);
|
void DrawFace(FString &defaultFace, int accuracy, bool xdth, bool animatedgodmode, int x, int y);
|
||||||
int updateState(bool xdth, bool animatedgodmode);
|
int updateState(bool xdth, bool animatedgodmode);
|
||||||
void DrawInventoryBar(int type, int num, int x, int y, bool alwaysshow,
|
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);
|
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);
|
DrawGraphic(Images[cmd.sprite], cmd.x, cmd.y, cmd.flags);
|
||||||
}
|
}
|
||||||
|
@ -571,7 +571,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
||||||
{
|
{
|
||||||
drawingFont = cmd.font;
|
drawingFont = cmd.font;
|
||||||
}
|
}
|
||||||
if(cmd.flags == DRAWNUMBER_HEALTH)
|
if(cmd.flags & DRAWNUMBER_HEALTH)
|
||||||
{
|
{
|
||||||
value = health;
|
value = health;
|
||||||
if(SBarInfoScript->lowerHealthCap && cmd.value < 0) //health shouldn't display negatives
|
if(SBarInfoScript->lowerHealthCap && cmd.value < 0) //health shouldn't display negatives
|
||||||
|
@ -579,11 +579,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(cmd.flags == DRAWNUMBER_ARMOR)
|
else if(cmd.flags & DRAWNUMBER_ARMOR)
|
||||||
{
|
{
|
||||||
value = armorAmount;
|
value = armorAmount;
|
||||||
}
|
}
|
||||||
else if(cmd.flags == DRAWNUMBER_AMMO1)
|
else if(cmd.flags & DRAWNUMBER_AMMO1)
|
||||||
{
|
{
|
||||||
value = ammocount1;
|
value = ammocount1;
|
||||||
if(ammo1 == NULL) //no ammo, do not draw
|
if(ammo1 == NULL) //no ammo, do not draw
|
||||||
|
@ -591,7 +591,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(cmd.flags == DRAWNUMBER_AMMO2)
|
else if(cmd.flags & DRAWNUMBER_AMMO2)
|
||||||
{
|
{
|
||||||
value = ammocount2;
|
value = ammocount2;
|
||||||
if(ammo2 == NULL) //no ammo, do not draw
|
if(ammo2 == NULL) //no ammo, do not draw
|
||||||
|
@ -599,7 +599,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(cmd.flags == DRAWNUMBER_AMMO)
|
else if(cmd.flags & DRAWNUMBER_AMMO)
|
||||||
{
|
{
|
||||||
const PClass* ammo = PClass::FindClass(cmd.string[0]);
|
const PClass* ammo = PClass::FindClass(cmd.string[0]);
|
||||||
AInventory* item = CPlayer->mo->FindInventory(ammo);
|
AInventory* item = CPlayer->mo->FindInventory(ammo);
|
||||||
|
@ -612,7 +612,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(cmd.flags == DRAWNUMBER_AMMOCAPACITY)
|
else if(cmd.flags & DRAWNUMBER_AMMOCAPACITY)
|
||||||
{
|
{
|
||||||
const PClass* ammo = PClass::FindClass(cmd.string[0]);
|
const PClass* ammo = PClass::FindClass(cmd.string[0]);
|
||||||
AInventory* item = CPlayer->mo->FindInventory(ammo);
|
AInventory* item = CPlayer->mo->FindInventory(ammo);
|
||||||
|
@ -625,21 +625,21 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
||||||
value = ((AInventory *)GetDefaultByType(ammo))->MaxAmount;
|
value = ((AInventory *)GetDefaultByType(ammo))->MaxAmount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(cmd.flags == DRAWNUMBER_FRAGS)
|
else if(cmd.flags & DRAWNUMBER_FRAGS)
|
||||||
value = CPlayer->fragcount;
|
value = CPlayer->fragcount;
|
||||||
else if(cmd.flags == DRAWNUMBER_KILLS)
|
else if(cmd.flags & DRAWNUMBER_KILLS)
|
||||||
value = level.killed_monsters;
|
value = level.killed_monsters;
|
||||||
else if(cmd.flags == DRAWNUMBER_MONSTERS)
|
else if(cmd.flags & DRAWNUMBER_MONSTERS)
|
||||||
value = level.total_monsters;
|
value = level.total_monsters;
|
||||||
else if(cmd.flags == DRAWNUMBER_ITEMS)
|
else if(cmd.flags & DRAWNUMBER_ITEMS)
|
||||||
value = level.found_items;
|
value = level.found_items;
|
||||||
else if(cmd.flags == DRAWNUMBER_TOTALITEMS)
|
else if(cmd.flags & DRAWNUMBER_TOTALITEMS)
|
||||||
value = level.total_items;
|
value = level.total_items;
|
||||||
else if(cmd.flags == DRAWNUMBER_SECRETS)
|
else if(cmd.flags & DRAWNUMBER_SECRETS)
|
||||||
value = level.found_secrets;
|
value = level.found_secrets;
|
||||||
else if(cmd.flags == DRAWNUMBER_TOTALSECRETS)
|
else if(cmd.flags & DRAWNUMBER_TOTALSECRETS)
|
||||||
value = level.total_secrets;
|
value = level.total_secrets;
|
||||||
else if(cmd.flags == DRAWNUMBER_ARMORCLASS)
|
else if(cmd.flags & DRAWNUMBER_ARMORCLASS)
|
||||||
{
|
{
|
||||||
AHexenArmor *harmor = CPlayer->mo->FindInventory<AHexenArmor>();
|
AHexenArmor *harmor = CPlayer->mo->FindInventory<AHexenArmor>();
|
||||||
if(harmor != NULL)
|
if(harmor != NULL)
|
||||||
|
@ -654,9 +654,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
||||||
}
|
}
|
||||||
value /= (5*FRACUNIT);
|
value /= (5*FRACUNIT);
|
||||||
}
|
}
|
||||||
else if(cmd.flags == DRAWNUMBER_GLOBALVAR)
|
else if(cmd.flags & DRAWNUMBER_GLOBALVAR)
|
||||||
value = ACS_GlobalVars[cmd.value];
|
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]));
|
AInventory* item = CPlayer->mo->FindInventory(PClass::FindClass(cmd.string[0]));
|
||||||
if(item != NULL)
|
if(item != NULL)
|
||||||
|
@ -668,12 +670,13 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(cmd.special3 != -1 && cmd.value <= cmd.special3) //low
|
bool fillzeros = !!(cmd.flags & DRAWNUMBER_FILLZEROS);
|
||||||
DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation2, cmd.special2);
|
if(cmd.special3 != -1 && value <= cmd.special3) //low
|
||||||
else if(cmd.special4 != -1 && cmd.value >= cmd.special4) //high
|
DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation2, cmd.special2, fillzeros);
|
||||||
DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation3, cmd.special2);
|
else if(cmd.special4 != -1 && value >= cmd.special4) //high
|
||||||
|
DrawNumber(value, cmd.special, cmd.x, cmd.y, cmd.translation3, cmd.special2, fillzeros);
|
||||||
else
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case SBARINFO_DRAWMUGSHOT:
|
case SBARINFO_DRAWMUGSHOT:
|
||||||
|
@ -1079,6 +1082,27 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
||||||
doCommands(cmd.subBlock);
|
doCommands(cmd.subBlock);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case SBARINFO_WEAPONAMMO:
|
||||||
if(CPlayer->ReadyWeapon != NULL)
|
if(CPlayer->ReadyWeapon != NULL)
|
||||||
{
|
{
|
||||||
|
@ -1154,6 +1178,10 @@ void DSBarInfo::doCommands(SBarInfoBlock &block)
|
||||||
//draws an image with the specified flags
|
//draws an image with the specified flags
|
||||||
void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int flags)
|
void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int flags)
|
||||||
{
|
{
|
||||||
|
if (texture == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if((flags & DRAWIMAGE_OFFSET_CENTER))
|
if((flags & DRAWIMAGE_OFFSET_CENTER))
|
||||||
{
|
{
|
||||||
x -= (texture->GetWidth()/2)-texture->LeftOffset;
|
x -= (texture->GetWidth()/2)-texture->LeftOffset;
|
||||||
|
@ -1162,8 +1190,9 @@ void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int flags)
|
||||||
x += ST_X;
|
x += ST_X;
|
||||||
y += ST_Y;
|
y += ST_Y;
|
||||||
int w = texture->GetScaledWidth();
|
int w = texture->GetScaledWidth();
|
||||||
int h = texture->GetScaledHeight();
|
int h = texture->GetScaledHeight() + y;
|
||||||
screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true);
|
screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true);
|
||||||
|
h -= y;
|
||||||
if((flags & DRAWIMAGE_TRANSLATABLE))
|
if((flags & DRAWIMAGE_TRANSLATABLE))
|
||||||
{
|
{
|
||||||
screen->DrawTexture(texture, x, y,
|
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
|
//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;
|
FString value;
|
||||||
int maxval = (int) ceil(pow(10., len))-1;
|
int maxval = (int) ceil(pow(10., len))-1;
|
||||||
num = clamp(num, -maxval, maxval);
|
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);
|
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')
|
if(SBarInfoScript->spacingCharacter == '\0')
|
||||||
x -= int(drawingFont->StringWidth(value)+(spacing * value.Len()));
|
x -= int(drawingFont->StringWidth(value)+(spacing * value.Len()));
|
||||||
else //monospaced so just multiplay the character size
|
else //monospaced so just multiplay the character size
|
||||||
|
@ -1245,16 +1289,20 @@ void DSBarInfo::DrawFace(FString &defaultFace, int accuracy, bool xdth, bool ani
|
||||||
for(level = 0;CPlayer->health < (accuracy-level-1)*(CPlayer->mo->GetMaxHealth()/accuracy);level++);
|
for(level = 0;CPlayer->health < (accuracy-level-1)*(CPlayer->mo->GetMaxHealth()/accuracy);level++);
|
||||||
if(currentState != NULL)
|
if(currentState != NULL)
|
||||||
{
|
{
|
||||||
FTexture *face = currentState->getCurrentFrameTexture(defaultFace, &skins[CPlayer->userinfo.skin], level, angle);
|
FPlayerSkin *skin = &skins[CPlayer->morphTics ? CPlayer->MorphedPlayerClass : CPlayer->userinfo.skin];
|
||||||
x += ST_X;
|
FTexture *face = currentState->getCurrentFrameTexture(defaultFace, skin, level, angle);
|
||||||
y += ST_Y;
|
if (face != NULL)
|
||||||
int w = face->GetScaledWidth();
|
{
|
||||||
int h = face->GetScaledHeight();
|
x += ST_X;
|
||||||
screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true);
|
y += ST_Y;
|
||||||
screen->DrawTexture(face, x, y,
|
int w = face->GetScaledWidth();
|
||||||
DTA_DestWidth, w,
|
int h = face->GetScaledHeight();
|
||||||
DTA_DestHeight, h,
|
screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true);
|
||||||
TAG_DONE);
|
screen->DrawTexture(face, x, y,
|
||||||
|
DTA_DestWidth, w,
|
||||||
|
DTA_DestHeight, h,
|
||||||
|
TAG_DONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1391,7 +1439,7 @@ void DSBarInfo::DrawInventoryBar(int type, int num, int x, int y, bool alwayssho
|
||||||
{
|
{
|
||||||
if(drawArtiboxes)
|
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);
|
DrawDimImage (TexMan(item->Icon), x+i*31, y, item->Amount <= 0);
|
||||||
if(alwaysshowcounter || item->Amount != 1)
|
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)
|
if(type == GAME_Heretic)
|
||||||
{
|
{
|
||||||
DrawImage(Images[invBarOffset + imgSELECTBOX], x+i*31, y+29);
|
DrawGraphic(Images[invBarOffset + imgSELECTBOX], x+i*31, y+29);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DrawImage(Images[invBarOffset + imgSELECTBOX], x+i*31, y);
|
DrawGraphic(Images[invBarOffset + imgSELECTBOX], x+i*31, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; i < num && drawArtiboxes; ++i)
|
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?
|
// Is there something to the left?
|
||||||
if (!noArrows && CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst)
|
if (!noArrows && CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst)
|
||||||
{
|
{
|
||||||
DrawImage (Images[!(gametic & 4) ?
|
DrawGraphic(Images[!(gametic & 4) ?
|
||||||
invBarOffset + imgINVLFGEM1 : invBarOffset + imgINVLFGEM2], x-12, y);
|
invBarOffset + imgINVLFGEM1 : invBarOffset + imgINVLFGEM2], x-12, y);
|
||||||
}
|
}
|
||||||
// Is there something to the right?
|
// Is there something to the right?
|
||||||
if (!noArrows && item != NULL)
|
if (!noArrows && item != NULL)
|
||||||
{
|
{
|
||||||
DrawImage (Images[!(gametic & 4) ?
|
DrawGraphic(Images[!(gametic & 4) ?
|
||||||
invBarOffset + imgINVRTGEM1 : invBarOffset + imgINVRTGEM2], x+num*31+2, y);
|
invBarOffset + imgINVRTGEM1 : invBarOffset + imgINVRTGEM2], x+num*31+2, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,7 @@ static const char *SBarInfoRoutineLevel[] =
|
||||||
"gamemode",
|
"gamemode",
|
||||||
"playerclass",
|
"playerclass",
|
||||||
"aspectratio",
|
"aspectratio",
|
||||||
|
"isselected",
|
||||||
"weaponammo", //event
|
"weaponammo", //event
|
||||||
"ininventory",
|
"ininventory",
|
||||||
NULL
|
NULL
|
||||||
|
@ -130,17 +131,14 @@ void SBarInfo::ParseSBarInfo(int lump)
|
||||||
{
|
{
|
||||||
gameType = gameinfo.gametype;
|
gameType = gameinfo.gametype;
|
||||||
bool baseSet = false;
|
bool baseSet = false;
|
||||||
FScanner sc(lump, Wads.GetLumpFullName(lump));
|
FScanner sc(lump);
|
||||||
sc.SetCMode(true);
|
sc.SetCMode(true);
|
||||||
while(sc.CheckToken(TK_Identifier) || sc.CheckToken(TK_Include))
|
while(sc.CheckToken(TK_Identifier) || sc.CheckToken(TK_Include))
|
||||||
{
|
{
|
||||||
if(sc.TokenType == TK_Include)
|
if(sc.TokenType == TK_Include)
|
||||||
{
|
{
|
||||||
sc.MustGetToken(TK_StringConst);
|
sc.MustGetToken(TK_StringConst);
|
||||||
int lump = Wads.CheckNumForFullName(sc.String); //zip/pk3
|
int lump = Wads.CheckNumForFullName(sc.String, true);
|
||||||
//Do a normal wad lookup.
|
|
||||||
if (lump == -1 && sc.StringLen <= 8 && !strchr(sc.String, '/'))
|
|
||||||
lump = Wads.CheckNumForName(sc.String);
|
|
||||||
if (lump == -1)
|
if (lump == -1)
|
||||||
sc.ScriptError("Lump '%s' not found", sc.String);
|
sc.ScriptError("Lump '%s' not found", sc.String);
|
||||||
ParseSBarInfo(lump);
|
ParseSBarInfo(lump);
|
||||||
|
@ -493,6 +491,14 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
||||||
sc.ScriptError("Global variable number out of range: %d", sc.Number);
|
sc.ScriptError("Global variable number out of range: %d", sc.Number);
|
||||||
cmd.value = 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
|
else
|
||||||
{
|
{
|
||||||
cmd.flags = DRAWNUMBER_INVENTORY;
|
cmd.flags = DRAWNUMBER_INVENTORY;
|
||||||
|
@ -506,6 +512,18 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
||||||
}
|
}
|
||||||
sc.MustGetToken(',');
|
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);
|
this->getCoordinates(sc, cmd);
|
||||||
if(sc.CheckToken(','))
|
if(sc.CheckToken(','))
|
||||||
{
|
{
|
||||||
|
@ -951,6 +969,33 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
||||||
sc.MustGetToken('{');
|
sc.MustGetToken('{');
|
||||||
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
||||||
break;
|
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:
|
case SBARINFO_WEAPONAMMO:
|
||||||
sc.MustGetToken(TK_Identifier);
|
sc.MustGetToken(TK_Identifier);
|
||||||
if(sc.Compare("not"))
|
if(sc.Compare("not"))
|
||||||
|
@ -983,7 +1028,6 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
||||||
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
||||||
break;
|
break;
|
||||||
case SBARINFO_ININVENTORY:
|
case SBARINFO_ININVENTORY:
|
||||||
{
|
|
||||||
sc.MustGetToken(TK_Identifier);
|
sc.MustGetToken(TK_Identifier);
|
||||||
if(sc.Compare("not"))
|
if(sc.Compare("not"))
|
||||||
{
|
{
|
||||||
|
@ -1014,7 +1058,6 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block)
|
||||||
sc.MustGetToken('{');
|
sc.MustGetToken('{');
|
||||||
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
this->ParseSBarInfoBlock(sc, cmd.subBlock);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
block.commands.Push(cmd);
|
block.commands.Push(cmd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -928,7 +928,7 @@ void HUD_InitHud()
|
||||||
|
|
||||||
while ((lump = Wads.FindLump ("ALTHUDCF", &lastlump)) != -1)
|
while ((lump = Wads.FindLump ("ALTHUDCF", &lastlump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(lump, "ALTHUDCF");
|
FScanner sc(lump);
|
||||||
while (sc.GetString())
|
while (sc.GetString())
|
||||||
{
|
{
|
||||||
if (sc.Compare("Health"))
|
if (sc.Compare("Health"))
|
||||||
|
|
|
@ -543,7 +543,7 @@ void A_KlaxonBlare (AActor *self)
|
||||||
A_TurretLook (self);
|
A_TurretLook (self);
|
||||||
if (self->target == NULL)
|
if (self->target == NULL)
|
||||||
{
|
{
|
||||||
self->SetState (self->SpawnState);
|
self->SetIdle();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -210,7 +210,7 @@ void A_JabDagger (AActor *actor)
|
||||||
|
|
||||||
angle = actor->angle + (pr_jabdagger.Random2() << 18);
|
angle = actor->angle + (pr_jabdagger.Random2() << 18);
|
||||||
pitch = P_AimLineAttack (actor, angle, 80*FRACUNIT);
|
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
|
// turn to face target
|
||||||
if (linetarget)
|
if (linetarget)
|
||||||
|
@ -934,7 +934,7 @@ void A_RocketInFlight (AActor *self)
|
||||||
AActor *trail;
|
AActor *trail;
|
||||||
|
|
||||||
S_Sound (self, CHAN_VOICE, "misc/missileinflight", 1, ATTN_NORM);
|
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);
|
trail = Spawn<ARocketTrail> (self->x - self->momx, self->y - self->momy, self->z, ALLOW_REPLACE);
|
||||||
if (trail != NULL)
|
if (trail != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1126,7 +1126,7 @@ void gl_DoParseDefs(FScanner &sc, int workingLump)
|
||||||
if (lump==-1)
|
if (lump==-1)
|
||||||
sc.ScriptError("Lump '%s' not found", sc.String);
|
sc.ScriptError("Lump '%s' not found", sc.String);
|
||||||
|
|
||||||
FScanner newscanner(lump, sc.String);
|
FScanner newscanner(lump);
|
||||||
gl_DoParseDefs(newscanner, lump);
|
gl_DoParseDefs(newscanner, lump);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1186,7 +1186,7 @@ void gl_LoadDynLightDefs(char * defsLump)
|
||||||
lastLump = 0;
|
lastLump = 0;
|
||||||
while ((workingLump = Wads.FindLump(defsLump, &lastLump)) != -1)
|
while ((workingLump = Wads.FindLump(defsLump, &lastLump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(workingLump, defsLump);
|
FScanner sc(workingLump);
|
||||||
gl_DoParseDefs(sc, workingLump);
|
gl_DoParseDefs(sc, workingLump);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,7 +247,7 @@ void gl_InitModels()
|
||||||
memset(&smf, 0, sizeof(smf));
|
memset(&smf, 0, sizeof(smf));
|
||||||
while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1)
|
while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(Lump, "MODELDEF");
|
FScanner sc(Lump);
|
||||||
while (sc.GetString())
|
while (sc.GetString())
|
||||||
{
|
{
|
||||||
if (sc.Compare("model"))
|
if (sc.Compare("model"))
|
||||||
|
|
|
@ -112,9 +112,9 @@ static void DrawPSprite (player_t * player,pspdef_t *psp,fixed_t sx, fixed_t sy,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fU2=pti->GetUL();
|
fU2=pti->GetUL();
|
||||||
fV2=pti->GetVT();
|
fV1=pti->GetVT();
|
||||||
fU1=pti->GetUR();
|
fU1=pti->GetUR();
|
||||||
fV1=pti->GetVB();
|
fV2=pti->GetVB();
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.Begin(GL_TRIANGLE_STRIP);
|
gl.Begin(GL_TRIANGLE_STRIP);
|
||||||
|
|
|
@ -247,6 +247,7 @@ enum
|
||||||
ADEF_PlayerPawn_CrouchSprite,
|
ADEF_PlayerPawn_CrouchSprite,
|
||||||
ADEF_PlayerPawn_DisplayName,
|
ADEF_PlayerPawn_DisplayName,
|
||||||
ADEF_PlayerPawn_SoundClass,
|
ADEF_PlayerPawn_SoundClass,
|
||||||
|
ADEF_PlayerPawn_Face,
|
||||||
ADEF_PlayerPawn_ScoreIcon,
|
ADEF_PlayerPawn_ScoreIcon,
|
||||||
ADEF_PlayerPawn_MorphWeapon,
|
ADEF_PlayerPawn_MorphWeapon,
|
||||||
ADEF_LastString = 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:
|
case ADEF_PlayerPawn_SoundClass:
|
||||||
sgClass->Meta.SetMetaString (APMETA_SoundClass, datastr);
|
sgClass->Meta.SetMetaString (APMETA_SoundClass, datastr);
|
||||||
break;
|
break;
|
||||||
|
case ADEF_PlayerPawn_Face:
|
||||||
|
sgClass->Meta.SetMetaString (APMETA_Face, datastr);
|
||||||
|
break;
|
||||||
case ADEF_PlayerPawn_ScoreIcon:
|
case ADEF_PlayerPawn_ScoreIcon:
|
||||||
player->ScoreIcon = TexMan.AddPatch (datastr);
|
player->ScoreIcon = TexMan.AddPatch (datastr);
|
||||||
if (player->ScoreIcon <= 0)
|
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_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_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_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_Face(x) ADD_STRING_PROP(ADEF_PlayerPawn_Face,"\27",x) // Octal - 'tis quaint!
|
||||||
#define PROP_PlayerPawn_MorphWeapon(x) ADD_STRING_PROP(ADEF_PlayerPawn_MorphWeapon,"\30",x)
|
#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_XScale(x) ADD_LONG_PROP(ADEF_XScale,x)
|
||||||
#define PROP_YScale(x) ADD_LONG_PROP(ADEF_YScale,x)
|
#define PROP_YScale(x) ADD_LONG_PROP(ADEF_YScale,x)
|
||||||
|
|
|
@ -1446,7 +1446,7 @@ void M_QuickLoad ()
|
||||||
//
|
//
|
||||||
void M_DrawReadThis ()
|
void M_DrawReadThis ()
|
||||||
{
|
{
|
||||||
FTexture *tex, *prevpic = NULL;
|
FTexture *tex = NULL, *prevpic = NULL;
|
||||||
fixed_t alpha;
|
fixed_t alpha;
|
||||||
|
|
||||||
if (gameinfo.flags & GI_INFOINDEXED)
|
if (gameinfo.flags & GI_INFOINDEXED)
|
||||||
|
@ -1463,11 +1463,15 @@ void M_DrawReadThis ()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tex = TexMan[gameinfo.info.infoPage[InfoType-1]];
|
|
||||||
// Did the mapper choose a custom help page via MAPINFO?
|
// 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)
|
if (InfoType > 1)
|
||||||
|
|
|
@ -492,6 +492,13 @@ static value_t ColumnMethods[] = {
|
||||||
{ 1.0, "Optimized" }
|
{ 1.0, "Optimized" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static value_t RocketTrailTypes[] = {
|
||||||
|
{ 0.0, "Off" },
|
||||||
|
{ 1.0, "Particles" },
|
||||||
|
{ 2.0, "Sprites" },
|
||||||
|
{ 3.0, "Sprites & Particles" }
|
||||||
|
};
|
||||||
|
|
||||||
static value_t BloodTypes[] = {
|
static value_t BloodTypes[] = {
|
||||||
{ 0.0, "Sprites" },
|
{ 0.0, "Sprites" },
|
||||||
{ 1.0, "Sprites & Particles" },
|
{ 1.0, "Sprites & Particles" },
|
||||||
|
@ -540,7 +547,7 @@ static menuitem_t VideoItems[] = {
|
||||||
#endif
|
#endif
|
||||||
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
|
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
|
||||||
{ discrete, "Use fuzz effect", {&r_drawfuzz}, {2.0}, {0.0}, {0.0}, {YesNo} },
|
{ 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, "Blood Type", {&cl_bloodtype}, {3.0}, {0.0}, {0.0}, {BloodTypes} },
|
||||||
{ discrete, "Bullet Puff Type", {&cl_pufftype}, {2.0}, {0.0}, {0.0}, {PuffTypes} },
|
{ 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)
|
EXTERN_CVAR (Bool, opl_onechip)
|
||||||
|
|
||||||
static menuitem_t AdvSoundItems[] =
|
static menuitem_t AdvSoundItems[] =
|
||||||
|
@ -3465,7 +3471,7 @@ void InitCrosshairsList()
|
||||||
|
|
||||||
while ((lump = Wads.FindLump("XHAIRS", &lastlump)) != -1)
|
while ((lump = Wads.FindLump("XHAIRS", &lastlump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(lump, "XHAIRS");
|
FScanner sc(lump);
|
||||||
while (sc.GetNumber())
|
while (sc.GetNumber())
|
||||||
{
|
{
|
||||||
value.value = float(sc.Number);
|
value.value = float(sc.Number);
|
||||||
|
|
|
@ -140,6 +140,7 @@ xx(Crush)
|
||||||
xx(Yes)
|
xx(Yes)
|
||||||
xx(No)
|
xx(No)
|
||||||
xx(Greetings)
|
xx(Greetings)
|
||||||
|
xx(Idle)
|
||||||
|
|
||||||
// Compatible death names for the decorate parser.
|
// Compatible death names for the decorate parser.
|
||||||
xx(XDeath)
|
xx(XDeath)
|
||||||
|
|
|
@ -75,17 +75,6 @@ Revision History:
|
||||||
#endif
|
#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 FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
|
||||||
#define EG_SH 16 /* 16.16 fixed point (EG timing) */
|
#define EG_SH 16 /* 16.16 fixed point (EG timing) */
|
||||||
#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */
|
#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include "zstring.h"
|
#include "zstring.h"
|
||||||
|
|
||||||
/* select output bits size of output : 8 or 16 */
|
// Multiplying OPL_SAMPLE_RATE by ADLIB_CLOCK_MUL gives the number
|
||||||
#define OPL_SAMPLE_BITS 16
|
// Adlib clocks per second, as used by the RAWADATA file format.
|
||||||
|
|
||||||
/* compiler dependence */
|
/* compiler dependence */
|
||||||
#ifndef OSD_CPU_H
|
#ifndef OSD_CPU_H
|
||||||
|
@ -17,13 +17,6 @@ typedef signed short INT16; /* signed 16bit */
|
||||||
typedef signed int INT32; /* signed 32bit */
|
typedef signed int INT32; /* signed 32bit */
|
||||||
#endif
|
#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_TIMERHANDLER)(int channel,double interval_Sec);
|
||||||
typedef void (*OPL_IRQHANDLER)(int param,int irq);
|
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 "muslib.h"
|
||||||
#include "fmopl.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)
|
void OPLio::OPLwriteReg(int which, uint reg, uchar data)
|
||||||
{
|
{
|
||||||
YM3812Write (which, 0, reg);
|
YM3812Write (which, 0, reg);
|
||||||
|
@ -106,64 +118,73 @@ static WORD frequencies[] =
|
||||||
0x1d9, 0x1da, 0x1db, 0x1dc, 0x1dd, 0x1de, 0x1de, 0x1df, 0x1e0, 0x1e1, 0x1e2, 0x1e3,
|
0x1d9, 0x1da, 0x1db, 0x1dc, 0x1dd, 0x1de, 0x1de, 0x1df, 0x1e0, 0x1e1, 0x1e2, 0x1e3,
|
||||||
0x1e4, 0x1e5, 0x1e5, 0x1e6, 0x1e7, 0x1e8, 0x1e9, 0x1ea, 0x1eb, 0x1ec, 0x1ed, 0x1ed,
|
0x1e4, 0x1e5, 0x1e5, 0x1e6, 0x1e7, 0x1e8, 0x1e9, 0x1ea, 0x1eb, 0x1ec, 0x1ed, 0x1ed,
|
||||||
0x1ee, 0x1ef, 0x1f0, 0x1f1, 0x1f2, 0x1f3, 0x1f4, 0x1f5, 0x1f6, 0x1f6, 0x1f7, 0x1f8,
|
0x1ee, 0x1ef, 0x1f0, 0x1f1, 0x1f2, 0x1f3, 0x1f4, 0x1f5, 0x1f6, 0x1f6, 0x1f7, 0x1f8,
|
||||||
0x1f9, 0x1fa, 0x1fb, 0x1fc, 0x1fd, 0x1fe, 0x1ff, 0x200, 0x201, 0x201, 0x202, 0x203,
|
0x1f9, 0x1fa, 0x1fb, 0x1fc, 0x1fd, 0x1fe, 0x1ff, 0x200,
|
||||||
0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20a, 0x20b, 0x20c, 0x20d, 0x20e, 0x20f,
|
|
||||||
0x210, 0x210, 0x211, 0x212, 0x213, 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21a,
|
0x201, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207, 0x208, 0x209, 0x20a, 0x20b, 0x20c, 0x20d, 0x20e, 0x20f,
|
||||||
0x21b, 0x21c, 0x21d, 0x21e, 0x21f, 0x220, 0x221, 0x222, 0x223, 0x224, 0x225, 0x226,
|
0x210, 0x210, 0x211, 0x212, 0x213, 0x214, 0x215, 0x216, 0x217, 0x218, 0x219, 0x21a, 0x21b, 0x21c, 0x21d, 0x21e,
|
||||||
0x227, 0x228, 0x229, 0x22a, 0x22b, 0x22c, 0x22d, 0x22e, 0x22f, 0x230, 0x231, 0x232,
|
|
||||||
0x233, 0x234, 0x235, 0x236, 0x237, 0x238, 0x239, 0x23a, 0x23b, 0x23c, 0x23d, 0x23e,
|
0x21f, 0x220, 0x221, 0x222, 0x223, 0x224, 0x225, 0x226, 0x227, 0x228, 0x229, 0x22a, 0x22b, 0x22c, 0x22d, 0x22e,
|
||||||
0x23f, 0x240, 0x241, 0x242, 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24a, 0x24b,
|
0x22f, 0x230, 0x231, 0x232, 0x233, 0x234, 0x235, 0x236, 0x237, 0x238, 0x239, 0x23a, 0x23b, 0x23c, 0x23d, 0x23e,
|
||||||
0x24c, 0x24d, 0x24e, 0x24f, 0x250, 0x251, 0x252, 0x253, 0x254, 0x256, 0x257, 0x258,
|
|
||||||
0x259, 0x25a, 0x25b, 0x25c, 0x25d, 0x25e, 0x25f, 0x260, 0x262, 0x263, 0x264, 0x265,
|
0x23f, 0x240, 0x241, 0x242, 0x244, 0x245, 0x246, 0x247, 0x248, 0x249, 0x24a, 0x24b, 0x24c, 0x24d, 0x24e, 0x24f,
|
||||||
0x266, 0x267, 0x268, 0x269, 0x26a, 0x26c, 0x26d, 0x26e, 0x26f, 0x270, 0x271, 0x272,
|
0x250, 0x251, 0x252, 0x253, 0x254, 0x256, 0x257, 0x258, 0x259, 0x25a, 0x25b, 0x25c, 0x25d, 0x25e, 0x25f, 0x260,
|
||||||
0x273, 0x275, 0x276, 0x277, 0x278, 0x279, 0x27a, 0x27b, 0x27d, 0x27e, 0x27f, 0x280,
|
|
||||||
0x281, 0x282, 0x284, 0x285, 0x286, 0x287, 0x288, 0x289, 0x28b, 0x28c, 0x28d, 0x28e,
|
0x262, 0x263, 0x264, 0x265, 0x266, 0x267, 0x268, 0x269, 0x26a, 0x26c, 0x26d, 0x26e, 0x26f, 0x270, 0x271, 0x272,
|
||||||
0x28f, 0x290, 0x292, 0x293, 0x294, 0x295, 0x296, 0x298, 0x299, 0x29a, 0x29b, 0x29c,
|
0x273, 0x275, 0x276, 0x277, 0x278, 0x279, 0x27a, 0x27b, 0x27d, 0x27e, 0x27f, 0x280, 0x281, 0x282, 0x284, 0x285,
|
||||||
0x29e, 0x29f, 0x2a0, 0x2a1, 0x2a2, 0x2a4, 0x2a5, 0x2a6, 0x2a7, 0x2a9, 0x2aa, 0x2ab,
|
|
||||||
0x2ac, 0x2ae, 0x2af, 0x2b0, 0x2b1, 0x2b2, 0x2b4, 0x2b5, 0x2b6, 0x2b7, 0x2b9, 0x2ba,
|
0x286, 0x287, 0x288, 0x289, 0x28b, 0x28c, 0x28d, 0x28e, 0x28f, 0x290, 0x292, 0x293, 0x294, 0x295, 0x296, 0x298,
|
||||||
0x2bb, 0x2bd, 0x2be, 0x2bf, 0x2c0, 0x2c2, 0x2c3, 0x2c4, 0x2c5, 0x2c7, 0x2c8, 0x2c9,
|
0x299, 0x29a, 0x29b, 0x29c, 0x29e, 0x29f, 0x2a0, 0x2a1, 0x2a2, 0x2a4, 0x2a5, 0x2a6, 0x2a7, 0x2a9, 0x2aa, 0x2ab,
|
||||||
0x2cb, 0x2cc, 0x2cd, 0x2ce, 0x2d0, 0x2d1, 0x2d2, 0x2d4, 0x2d5, 0x2d6, 0x2d8, 0x2d9,
|
|
||||||
0x2da, 0x2dc, 0x2dd, 0x2de, 0x2e0, 0x2e1, 0x2e2, 0x2e4, 0x2e5, 0x2e6, 0x2e8, 0x2e9,
|
0x2ac, 0x2ae, 0x2af, 0x2b0, 0x2b1, 0x2b2, 0x2b4, 0x2b5, 0x2b6, 0x2b7, 0x2b9, 0x2ba, 0x2bb, 0x2bd, 0x2be, 0x2bf,
|
||||||
0x2ea, 0x2ec, 0x2ed, 0x2ee, 0x2f0, 0x2f1, 0x2f2, 0x2f4, 0x2f5, 0x2f6, 0x2f8, 0x2f9,
|
0x2c0, 0x2c2, 0x2c3, 0x2c4, 0x2c5, 0x2c7, 0x2c8, 0x2c9, 0x2cb, 0x2cc, 0x2cd, 0x2ce, 0x2d0, 0x2d1, 0x2d2, 0x2d4,
|
||||||
0x2fb, 0x2fc, 0x2fd, 0x2ff, 0x300, 0x302, 0x303, 0x304, 0x306, 0x307, 0x309, 0x30a,
|
|
||||||
0x30b, 0x30d, 0x30e, 0x310, 0x311, 0x312, 0x314, 0x315, 0x317, 0x318, 0x31a, 0x31b,
|
0x2d5, 0x2d6, 0x2d8, 0x2d9, 0x2da, 0x2dc, 0x2dd, 0x2de, 0x2e0, 0x2e1, 0x2e2, 0x2e4, 0x2e5, 0x2e6, 0x2e8, 0x2e9,
|
||||||
0x31c, 0x31e, 0x31f, 0x321, 0x322, 0x324, 0x325, 0x327, 0x328, 0x329, 0x32b, 0x32c,
|
0x2ea, 0x2ec, 0x2ed, 0x2ee, 0x2f0, 0x2f1, 0x2f2, 0x2f4, 0x2f5, 0x2f6, 0x2f8, 0x2f9, 0x2fb, 0x2fc, 0x2fd, 0x2ff,
|
||||||
0x32e, 0x32f, 0x331, 0x332, 0x334, 0x335, 0x337, 0x338, 0x33a, 0x33b, 0x33d, 0x33e,
|
|
||||||
0x340, 0x341, 0x343, 0x344, 0x346, 0x347, 0x349, 0x34a, 0x34c, 0x34d, 0x34f, 0x350,
|
0x300, 0x302, 0x303, 0x304, 0x306, 0x307, 0x309, 0x30a, 0x30b, 0x30d, 0x30e, 0x310, 0x311, 0x312, 0x314, 0x315,
|
||||||
0x352, 0x353, 0x355, 0x357, 0x358, 0x35a, 0x35b, 0x35d, 0x35e, 0x360, 0x361, 0x363,
|
0x317, 0x318, 0x31a, 0x31b, 0x31c, 0x31e, 0x31f, 0x321, 0x322, 0x324, 0x325, 0x327, 0x328, 0x329, 0x32b, 0x32c,
|
||||||
0x365, 0x366, 0x368, 0x369, 0x36b, 0x36c, 0x36e, 0x370, 0x371, 0x373, 0x374, 0x376,
|
|
||||||
0x378, 0x379, 0x37b, 0x37c, 0x37e, 0x380, 0x381, 0x383, 0x384, 0x386, 0x388, 0x389,
|
0x32e, 0x32f, 0x331, 0x332, 0x334, 0x335, 0x337, 0x338, 0x33a, 0x33b, 0x33d, 0x33e, 0x340, 0x341, 0x343, 0x344,
|
||||||
0x38b, 0x38d, 0x38e, 0x390, 0x392, 0x393, 0x395, 0x397, 0x398, 0x39a, 0x39c, 0x39d,
|
0x346, 0x347, 0x349, 0x34a, 0x34c, 0x34d, 0x34f, 0x350, 0x352, 0x353, 0x355, 0x357, 0x358, 0x35a, 0x35b, 0x35d,
|
||||||
0x39f, 0x3a1, 0x3a2, 0x3a4, 0x3a6, 0x3a7, 0x3a9, 0x3ab, 0x3ac, 0x3ae, 0x3b0, 0x3b1,
|
|
||||||
0x3b3, 0x3b5, 0x3b7, 0x3b8, 0x3ba, 0x3bc, 0x3bd, 0x3bf, 0x3c1, 0x3c3, 0x3c4, 0x3c6,
|
0x35e, 0x360, 0x361, 0x363, 0x365, 0x366, 0x368, 0x369, 0x36b, 0x36c, 0x36e, 0x370, 0x371, 0x373, 0x374, 0x376,
|
||||||
0x3c8, 0x3ca, 0x3cb, 0x3cd, 0x3cf, 0x3d1, 0x3d2, 0x3d4, 0x3d6, 0x3d8, 0x3da, 0x3db,
|
0x378, 0x379, 0x37b, 0x37c, 0x37e, 0x380, 0x381, 0x383, 0x384, 0x386, 0x388, 0x389, 0x38b, 0x38d, 0x38e, 0x390,
|
||||||
0x3dd, 0x3df, 0x3e1, 0x3e3, 0x3e4, 0x3e6, 0x3e8, 0x3ea, 0x3ec, 0x3ed, 0x3ef, 0x3f1,
|
|
||||||
0x3f3, 0x3f5, 0x3f6, 0x3f8, 0x3fa, 0x3fc, 0x3fe, 0x36c, 0x388
|
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
|
* 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 octave = 0;
|
||||||
int j = (freq<<5) + octave;
|
int j = (note << 5) + pitch;
|
||||||
i = 0;
|
|
||||||
if (j < 0)
|
if (j < 0)
|
||||||
{
|
{
|
||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
else if (j >= 0x11C)
|
else if (j >= 284)
|
||||||
{
|
{
|
||||||
j -= 0x11C;
|
j -= 284;
|
||||||
i = j / 0x180;
|
octave = j / (32*12);
|
||||||
if (i > 7)
|
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 (0xA0, channel, (BYTE)i);
|
||||||
OPLwriteValue (0xB0, channel, (BYTE)(i>>8)|(keyon<<5));
|
OPLwriteValue (0xB0, channel, (BYTE)(i>>8)|(keyon<<5));
|
||||||
|
@ -277,20 +298,12 @@ void OPLio::OPLshutup(void)
|
||||||
/*
|
/*
|
||||||
* Initialize hardware upon startup
|
* 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;
|
||||||
|
OPLwriteInitState();
|
||||||
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();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
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
|
* Deinitialize hardware before shutdown
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "m_swap.h"
|
#include "m_swap.h"
|
||||||
#include "w_wad.h"
|
#include "w_wad.h"
|
||||||
|
#include "fmopl.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -105,7 +106,7 @@ OPLMIDIDevice::~OPLMIDIDevice()
|
||||||
|
|
||||||
int OPLMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata)
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -209,6 +210,7 @@ int OPLMIDIDevice::SetTimeDiv(int timediv)
|
||||||
void OPLMIDIDevice::CalcTickRate()
|
void OPLMIDIDevice::CalcTickRate()
|
||||||
{
|
{
|
||||||
SamplesPerTick = OPL_SAMPLE_RATE / (1000000.0 / Tempo) / Division;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -130,7 +130,7 @@ struct OP2instrEntry {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FL_FIXED_PITCH 0x0001 // note has fixed pitch (see below)
|
#define FL_FIXED_PITCH 0x0001 // note has fixed pitch (see below)
|
||||||
#define FL_UNKNOWN 0x0002 // ??? (used in instrument #65 only)
|
#define FL_UNKNOWN 0x0002 // ??? (used in instrument #65 only)
|
||||||
#define FL_DOUBLE_VOICE 0x0004 // use two voices instead of one
|
#define FL_DOUBLE_VOICE 0x0004 // use two voices instead of one
|
||||||
|
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ struct OPLdata {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OPLio {
|
struct OPLio {
|
||||||
virtual ~OPLio() {}
|
virtual ~OPLio();
|
||||||
|
|
||||||
void OPLwriteChannel(uint regbase, uint channel, uchar data1, uchar data2);
|
void OPLwriteChannel(uint regbase, uint channel, uchar data1, uchar data2);
|
||||||
void OPLwriteValue(uint regbase, uint channel, uchar value);
|
void OPLwriteValue(uint regbase, uint channel, uchar value);
|
||||||
|
@ -171,14 +171,43 @@ struct OPLio {
|
||||||
void OPLwritePan(uint channel, struct OPL2instrument *instr, int pan);
|
void OPLwritePan(uint channel, struct OPL2instrument *instr, int pan);
|
||||||
void OPLwriteInstrument(uint channel, struct OPL2instrument *instr);
|
void OPLwriteInstrument(uint channel, struct OPL2instrument *instr);
|
||||||
void OPLshutup(void);
|
void OPLshutup(void);
|
||||||
|
void OPLwriteInitState();
|
||||||
|
|
||||||
virtual int OPLinit(uint numchips, uint rate);
|
virtual int OPLinit(uint numchips);
|
||||||
virtual void OPLdeinit(void);
|
virtual void OPLdeinit(void);
|
||||||
virtual void OPLwriteReg(int which, uint reg, uchar data);
|
virtual void OPLwriteReg(int which, uint reg, uchar data);
|
||||||
|
virtual void SetClockRate(double samples_per_tick);
|
||||||
|
virtual void WriteDelay(int ticks);
|
||||||
|
|
||||||
uint OPLchannels;
|
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 {
|
struct musicBlock {
|
||||||
musicBlock();
|
musicBlock();
|
||||||
~musicBlock();
|
~musicBlock();
|
||||||
|
@ -193,8 +222,6 @@ struct musicBlock {
|
||||||
|
|
||||||
ulong MLtime;
|
ulong MLtime;
|
||||||
|
|
||||||
int playTick();
|
|
||||||
|
|
||||||
void OPLplayNote(uint channel, uchar note, int volume);
|
void OPLplayNote(uint channel, uchar note, int volume);
|
||||||
void OPLreleaseNote(uint channel, uchar note);
|
void OPLreleaseNote(uint channel, uchar note);
|
||||||
void OPLpitchWheel(uint channel, int pitch);
|
void OPLpitchWheel(uint channel, int pitch);
|
||||||
|
@ -254,4 +281,7 @@ enum MUSctrl {
|
||||||
ctrlResetCtrls
|
ctrlResetCtrls
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define OPL_SAMPLE_RATE 49716.0
|
||||||
|
#define ADLIB_CLOCK_MUL 24.0
|
||||||
|
|
||||||
#endif // __MUSLIB_H_
|
#endif // __MUSLIB_H_
|
||||||
|
|
|
@ -79,7 +79,7 @@ void OPLmusicBlock::ResetChips ()
|
||||||
TwoChips = !opl_onechip;
|
TwoChips = !opl_onechip;
|
||||||
Serialize();
|
Serialize();
|
||||||
io->OPLdeinit ();
|
io->OPLdeinit ();
|
||||||
io->OPLinit (TwoChips + 1, uint(OPL_SAMPLE_RATE));
|
io->OPLinit (TwoChips + 1);
|
||||||
Unserialize();
|
Unserialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ void OPLmusicBlock::Restart()
|
||||||
playingcount = 0;
|
playingcount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
OPLmusicFile::OPLmusicFile (FILE *file, char * musiccache, int len, int maxSamples)
|
OPLmusicFile::OPLmusicFile (FILE *file, char *musiccache, int len)
|
||||||
: ScoreLen (len)
|
: ScoreLen (len)
|
||||||
{
|
{
|
||||||
if (io == NULL)
|
if (io == NULL)
|
||||||
|
@ -115,29 +115,15 @@ OPLmusicFile::OPLmusicFile (FILE *file, char * musiccache, int len, int maxSampl
|
||||||
memcpy(scoredata, &musiccache[0], len);
|
memcpy(scoredata, &musiccache[0], len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (io->OPLinit (TwoChips + 1, uint(OPL_SAMPLE_RATE)))
|
if (io->OPLinit (TwoChips + 1))
|
||||||
{
|
{
|
||||||
delete[] scoredata;
|
delete[] scoredata;
|
||||||
scoredata = NULL;
|
scoredata = NULL;
|
||||||
return;
|
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
|
// 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'))
|
((DWORD *)scoredata)[1] == MAKE_ID('D','A','T','A'))
|
||||||
{
|
{
|
||||||
RawPlayer = RDosPlay;
|
RawPlayer = RDosPlay;
|
||||||
|
@ -145,7 +131,16 @@ OPLmusicFile::OPLmusicFile (FILE *file, char * musiccache, int len, int maxSampl
|
||||||
{ // A clock speed of 0 is bad
|
{ // A clock speed of 0 is bad
|
||||||
*(WORD *)(scoredata + 8) = 0xFFFF;
|
*(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)
|
// Check for modified IMF format (includes a header)
|
||||||
else if (((DWORD *)scoredata)[0] == MAKE_ID('A','D','L','I') &&
|
else if (((DWORD *)scoredata)[0] == MAKE_ID('A','D','L','I') &&
|
||||||
|
@ -202,14 +197,16 @@ void OPLmusicFile::SetLooping (bool loop)
|
||||||
void OPLmusicFile::Restart ()
|
void OPLmusicFile::Restart ()
|
||||||
{
|
{
|
||||||
OPLmusicBlock::Restart();
|
OPLmusicBlock::Restart();
|
||||||
if (RawPlayer == NotRaw)
|
WhichChip = 0;
|
||||||
{
|
if (RawPlayer == RDosPlay)
|
||||||
score = scoredata + ((MUSheader *)scoredata)->scoreStart;
|
|
||||||
}
|
|
||||||
else if (RawPlayer == RDosPlay)
|
|
||||||
{
|
{
|
||||||
score = scoredata + 10;
|
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)
|
else if (RawPlayer == IMF)
|
||||||
{
|
{
|
||||||
|
@ -226,6 +223,7 @@ void OPLmusicFile::Restart ()
|
||||||
score += 4; // Skip song length
|
score += 4; // Skip song length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
io->SetClockRate(SamplesPerTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
|
bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
|
||||||
|
@ -289,6 +287,7 @@ bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prevEnded = false;
|
prevEnded = false;
|
||||||
|
io->WriteDelay(next);
|
||||||
NextTickIn += SamplesPerTick * next;
|
NextTickIn += SamplesPerTick * next;
|
||||||
assert (NextTickIn >= 0);
|
assert (NextTickIn >= 0);
|
||||||
MLtime += next;
|
MLtime += next;
|
||||||
|
@ -303,11 +302,7 @@ int OPLmusicFile::PlayTick ()
|
||||||
{
|
{
|
||||||
BYTE reg, data;
|
BYTE reg, data;
|
||||||
|
|
||||||
if (RawPlayer == NotRaw)
|
if (RawPlayer == RDosPlay)
|
||||||
{
|
|
||||||
return playTick ();
|
|
||||||
}
|
|
||||||
else if (RawPlayer == RDosPlay)
|
|
||||||
{
|
{
|
||||||
while (score < scoredata + ScoreLen)
|
while (score < scoredata + ScoreLen)
|
||||||
{
|
{
|
||||||
|
@ -325,9 +320,18 @@ int OPLmusicFile::PlayTick ()
|
||||||
case 2: // Speed change or OPL3 switch
|
case 2: // Speed change or OPL3 switch
|
||||||
if (data == 0)
|
if (data == 0)
|
||||||
{
|
{
|
||||||
SamplesPerTick = OPL_SAMPLE_RATE * LittleShort(*(WORD *)(score)) / 1193180.0;
|
SamplesPerTick = LittleShort(*(WORD *)(score)) / ADLIB_CLOCK_MUL;
|
||||||
|
io->SetClockRate(SamplesPerTick);
|
||||||
score += 2;
|
score += 2;
|
||||||
}
|
}
|
||||||
|
else if (data == 1)
|
||||||
|
{
|
||||||
|
WhichChip = 0;
|
||||||
|
}
|
||||||
|
else if (data == 2)
|
||||||
|
{
|
||||||
|
WhichChip = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFF: // End of song
|
case 0xFF: // End of song
|
||||||
|
@ -338,11 +342,55 @@ int OPLmusicFile::PlayTick ()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // It's something to stuff into the OPL chip
|
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;
|
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)
|
else if (RawPlayer == IMF)
|
||||||
{
|
{
|
||||||
WORD delay = 0;
|
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) {}
|
ScoreLen = source->ScoreLen;
|
||||||
virtual ~DiskWriterIO () { if (File != NULL) fclose (File); }
|
scoredata = new BYTE[ScoreLen];
|
||||||
int OPLinit(const char *filename);
|
memcpy(scoredata, source->scoredata, ScoreLen);
|
||||||
virtual void OPLwriteReg(int which, uint reg, uchar data);
|
SamplesPerTick = source->SamplesPerTick;
|
||||||
|
RawPlayer = source->RawPlayer;
|
||||||
FILE *File;
|
score = source->score;
|
||||||
bool RawFormat;
|
TwoChips = source->TwoChips;
|
||||||
};
|
WhichChip = 0;
|
||||||
|
if (io != NULL)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (BlockForStats == NULL)
|
delete io;
|
||||||
{
|
|
||||||
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 ();
|
|
||||||
}
|
}
|
||||||
|
io = new DiskWriterIO(filename);
|
||||||
|
io->OPLinit(TwoChips);
|
||||||
|
Restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
OPLmusicWriter::~OPLmusicWriter ()
|
void OPLmusicFile::Dump()
|
||||||
{
|
{
|
||||||
if (io != NULL) delete io;
|
int time;
|
||||||
if (!SharingData)
|
|
||||||
|
time = PlayTick();
|
||||||
|
while (time != 0)
|
||||||
{
|
{
|
||||||
delete scoredata;
|
io->WriteDelay(time);
|
||||||
}
|
time = PlayTick();
|
||||||
else
|
|
||||||
{
|
|
||||||
OPLinstruments = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 "muslib.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
|
||||||
#define OPL_SAMPLE_RATE 49716.0
|
|
||||||
|
|
||||||
class OPLmusicBlock : public musicBlock
|
class OPLmusicBlock : public musicBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OPLmusicBlock();
|
OPLmusicBlock();
|
||||||
~OPLmusicBlock();
|
virtual ~OPLmusicBlock();
|
||||||
|
|
||||||
bool ServiceStream(void *buff, int numbytes);
|
bool ServiceStream(void *buff, int numbytes);
|
||||||
void ResetChips();
|
void ResetChips();
|
||||||
|
@ -43,16 +41,20 @@ protected:
|
||||||
class OPLmusicFile : public OPLmusicBlock
|
class OPLmusicFile : public OPLmusicBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OPLmusicFile(FILE *file, char *musiccache, int len, int maxSamples);
|
OPLmusicFile(FILE *file, char *musiccache, int len);
|
||||||
~OPLmusicFile();
|
OPLmusicFile(const OPLmusicFile *source, const char *filename);
|
||||||
|
virtual ~OPLmusicFile();
|
||||||
|
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
void SetLooping(bool loop);
|
void SetLooping(bool loop);
|
||||||
void Restart();
|
void Restart();
|
||||||
|
void Dump();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
OPLmusicFile() {}
|
||||||
int PlayTick();
|
int PlayTick();
|
||||||
|
|
||||||
enum { NotRaw, RDosPlay, IMF } RawPlayer;
|
enum { RDosPlay, IMF, DosBox } RawPlayer;
|
||||||
int ScoreLen;
|
int ScoreLen;
|
||||||
|
int WhichChip;
|
||||||
};
|
};
|
||||||
|
|
|
@ -556,7 +556,7 @@ void FBehavior::StaticLoadDefaultModules ()
|
||||||
|
|
||||||
while ((lump = Wads.FindLump ("LOADACS", &lastlump)) != -1)
|
while ((lump = Wads.FindLump ("LOADACS", &lastlump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(lump, "LOADACS");
|
FScanner sc(lump);
|
||||||
while (sc.GetString())
|
while (sc.GetString())
|
||||||
{
|
{
|
||||||
int acslump = Wads.CheckNumForName (sc.String, ns_acslibrary);
|
int acslump = Wads.CheckNumForName (sc.String, ns_acslibrary);
|
||||||
|
|
|
@ -228,7 +228,7 @@ void P_RunEffect (AActor *actor, int effects)
|
||||||
particle_t *particle;
|
particle_t *particle;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ((effects & FX_ROCKET) && cl_rockettrails)
|
if ((effects & FX_ROCKET) && (cl_rockettrails & 1))
|
||||||
{
|
{
|
||||||
// Rocket trail
|
// Rocket trail
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ void P_RunEffect (AActor *actor, int effects)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((effects & FX_GRENADE) && (cl_rockettrails))
|
if ((effects & FX_GRENADE) && (cl_rockettrails & 1))
|
||||||
{
|
{
|
||||||
// Grenade trail
|
// Grenade trail
|
||||||
|
|
||||||
|
|
|
@ -1884,7 +1884,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
actor->SetState (actor->SpawnState);
|
actor->SetIdle();
|
||||||
actor->flags &= ~MF_INCHASE;
|
actor->flags &= ~MF_INCHASE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1945,7 +1945,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
|
||||||
if (newgoal != NULL && delay != 0)
|
if (newgoal != NULL && delay != 0)
|
||||||
{
|
{
|
||||||
actor->flags4 |= MF4_INCOMBAT;
|
actor->flags4 |= MF4_INCOMBAT;
|
||||||
actor->SetState (actor->SpawnState);
|
actor->SetIdle();
|
||||||
}
|
}
|
||||||
actor->flags &= ~MF_INCHASE;
|
actor->flags &= ~MF_INCHASE;
|
||||||
actor->goal = newgoal;
|
actor->goal = newgoal;
|
||||||
|
|
|
@ -90,13 +90,20 @@ void P_UnPredictPlayer ();
|
||||||
extern fixed_t FloatBobOffsets[64];
|
extern fixed_t FloatBobOffsets[64];
|
||||||
extern AActor *MissileActor;
|
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);
|
void P_ThrustMobj (AActor *mo, angle_t angle, fixed_t move);
|
||||||
int P_FaceMobj (AActor *source, AActor *target, angle_t *delta);
|
int P_FaceMobj (AActor *source, AActor *target, angle_t *delta);
|
||||||
bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax);
|
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_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_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);
|
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)
|
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);
|
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, 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);
|
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, 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, angle_t angle, int pitch);
|
||||||
void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version
|
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,
|
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;
|
fixed_t vx, vy, vz, shootz;
|
||||||
FTraceResults trace;
|
FTraceResults trace;
|
||||||
|
@ -3079,6 +3079,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
||||||
bool hitGhosts;
|
bool hitGhosts;
|
||||||
bool killPuff = false;
|
bool killPuff = false;
|
||||||
AActor *puff = NULL;
|
AActor *puff = NULL;
|
||||||
|
int flags = ismeleeattack? PF_MELEERANGE : 0;
|
||||||
|
|
||||||
angle >>= ANGLETOFINESHIFT;
|
angle >>= ANGLETOFINESHIFT;
|
||||||
pitch = (angle_t)(pitch) >> 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)
|
if (puffDefaults->flags3 & MF3_ALWAYSPUFF)
|
||||||
{ // Spawn the puff anyway
|
{ // 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
|
else
|
||||||
{
|
{
|
||||||
|
@ -3133,7 +3134,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
||||||
fixed_t closer = trace.Distance - 4*FRACUNIT;
|
fixed_t closer = trace.Distance - 4*FRACUNIT;
|
||||||
puff = P_SpawnPuff (pufftype, t1->x + FixedMul (vx, closer),
|
puff = P_SpawnPuff (pufftype, t1->x + FixedMul (vx, closer),
|
||||||
t1->y + FixedMul (vy, 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
|
// [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->flags & MF_NOBLOOD) ||
|
||||||
(trace.Actor->flags2 & (MF2_INVULNERABLE|MF2_DORMANT)))
|
(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))
|
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
|
// Since the puff is the damage inflictor we need it here
|
||||||
// regardless of whether it is displayed or not.
|
// 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;
|
killPuff = true;
|
||||||
}
|
}
|
||||||
P_DamageMobj (trace.Actor, puff ? puff : t1, t1, damage, damageType, flags);
|
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)
|
if (puff == NULL)
|
||||||
{ // Spawn puff just to get a mass for the splash
|
{ // 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;
|
killPuff = true;
|
||||||
}
|
}
|
||||||
SpawnDeepSplash (t1, trace, puff, vx, vy, vz);
|
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,
|
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);
|
const PClass * type = PClass::FindClass(pufftype);
|
||||||
if (type == NULL)
|
if (type == NULL)
|
||||||
|
@ -3268,7 +3269,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type);
|
return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, ismeleeattack);
|
||||||
}
|
}
|
||||||
return NULL;
|
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) ||
|
if ((RailHits[i].HitActor->flags & MF_NOBLOOD) ||
|
||||||
(RailHits[i].HitActor->flags2 & (MF2_DORMANT|MF2_INVULNERABLE)))
|
(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
|
else
|
||||||
{
|
{
|
||||||
|
|
914
src/p_mobj.cpp
914
src/p_mobj.cpp
File diff suppressed because it is too large
Load diff
|
@ -46,6 +46,7 @@
|
||||||
#include "p_lnspec.h"
|
#include "p_lnspec.h"
|
||||||
#include "v_palette.h"
|
#include "v_palette.h"
|
||||||
#include "c_console.h"
|
#include "c_console.h"
|
||||||
|
#include "c_cvars.h"
|
||||||
#include "p_acs.h"
|
#include "p_acs.h"
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
#include "announcer.h"
|
#include "announcer.h"
|
||||||
|
@ -64,7 +65,7 @@
|
||||||
|
|
||||||
#include "fragglescript/t_fs.h"
|
#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 bool P_LoadBuildMap (BYTE *mapdata, size_t len, mapthing2_t **things, int *numthings);
|
||||||
|
|
||||||
extern void P_LoadTranslator(const char *lump);
|
extern void P_LoadTranslator(const char *lump);
|
||||||
|
@ -283,7 +284,7 @@ MapData *P_OpenMapData(const char * mapname)
|
||||||
if (lumpfile != nextfile)
|
if (lumpfile != nextfile)
|
||||||
{
|
{
|
||||||
// The following lump is from a different file so whatever this is,
|
// 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;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +384,13 @@ MapData *P_OpenMapData(const char * mapname)
|
||||||
return map;
|
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;
|
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.angle = LittleShort(mt->angle);
|
||||||
mt2.type = LittleShort(mt->type);
|
mt2.type = LittleShort(mt->type);
|
||||||
|
|
||||||
P_SpawnMapThing (&mt2, position);
|
SpawnMapThing (i, &mt2, position);
|
||||||
}
|
}
|
||||||
delete [] mtp;
|
delete [] mtp;
|
||||||
}
|
}
|
||||||
|
@ -1756,7 +1782,7 @@ void P_LoadThings2 (MapData * map, int position)
|
||||||
|
|
||||||
for (i=0, mt = (mapthing2_t*)mtp; i < numthings; i++,mt++)
|
for (i=0, mt = (mapthing2_t*)mtp; i < numthings; i++,mt++)
|
||||||
{
|
{
|
||||||
P_SpawnMapThing (mt, position);
|
SpawnMapThing (i, mt, position);
|
||||||
}
|
}
|
||||||
delete[] mtp;
|
delete[] mtp;
|
||||||
}
|
}
|
||||||
|
@ -3869,7 +3895,7 @@ void P_SetupLevel (char *lumpname, int position)
|
||||||
{
|
{
|
||||||
for (i = 0; i < numbuildthings; ++i)
|
for (i = 0; i < numbuildthings; ++i)
|
||||||
{
|
{
|
||||||
P_SpawnMapThing (&buildthings[i], 0);
|
SpawnMapThing (i, &buildthings[i], 0);
|
||||||
}
|
}
|
||||||
delete[] buildthings;
|
delete[] buildthings;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@ struct MapData
|
||||||
};
|
};
|
||||||
|
|
||||||
MapData * P_OpenMapData(const char * mapname);
|
MapData * P_OpenMapData(const char * mapname);
|
||||||
|
bool P_CheckMapData(const char * mapname);
|
||||||
|
|
||||||
// NOT called by W_Ticker. Fixme. [RH] Is that bad?
|
// NOT called by W_Ticker. Fixme. [RH] Is that bad?
|
||||||
//
|
//
|
||||||
|
|
|
@ -370,7 +370,7 @@ FSwitchDef *ParseSwitchDef (FScanner &sc, bool ignoreBad)
|
||||||
thisframe.Time = ((max - min + 1) << 16) | min;
|
thisframe.Time = ((max - min + 1) << 16) | min;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thisframe.Time = 0; // Shush, GCC.
|
thisframe.Time = 0; // Shush, GCC.
|
||||||
sc.ScriptError ("Must specify a duration for switch frame");
|
sc.ScriptError ("Must specify a duration for switch frame");
|
||||||
}
|
}
|
||||||
|
@ -475,6 +475,9 @@ static int TryFindSwitch (side_t *side, int Where)
|
||||||
//
|
//
|
||||||
bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno)
|
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 checktop;
|
||||||
fixed_t checkbot;
|
fixed_t checkbot;
|
||||||
side_t *side = &sides[line->sidenum[sideno]];
|
side_t *side = &sides[line->sidenum[sideno]];
|
||||||
|
|
|
@ -267,7 +267,7 @@ void P_InitTerrainTypes ()
|
||||||
lastlump = 0;
|
lastlump = 0;
|
||||||
while (-1 != (lump = Wads.FindLump ("TERRAIN", &lastlump)) )
|
while (-1 != (lump = Wads.FindLump ("TERRAIN", &lastlump)) )
|
||||||
{
|
{
|
||||||
FScanner sc(lump, "TERRAIN");
|
FScanner sc(lump);
|
||||||
ParseOuter (sc);
|
ParseOuter (sc);
|
||||||
}
|
}
|
||||||
Splashes.ShrinkToFit ();
|
Splashes.ShrinkToFit ();
|
||||||
|
|
|
@ -422,6 +422,7 @@ BEGIN_STATELESS_DEFAULTS (APlayerPawn, Any, -1, 0)
|
||||||
PROP_PlayerPawn_SideMove2 (FRACUNIT)
|
PROP_PlayerPawn_SideMove2 (FRACUNIT)
|
||||||
PROP_PlayerPawn_ColorRange (0, 0)
|
PROP_PlayerPawn_ColorRange (0, 0)
|
||||||
PROP_PlayerPawn_SoundClass ("player")
|
PROP_PlayerPawn_SoundClass ("player")
|
||||||
|
PROP_PlayerPawn_Face ("None")
|
||||||
PROP_PlayerPawn_MorphWeapon ("None")
|
PROP_PlayerPawn_MorphWeapon ("None")
|
||||||
END_DEFAULTS
|
END_DEFAULTS
|
||||||
|
|
||||||
|
|
|
@ -289,7 +289,7 @@ static void R_InitAnimDefs ()
|
||||||
|
|
||||||
while ((lump = Wads.FindLump ("ANIMDEFS", &lastlump)) != -1)
|
while ((lump = Wads.FindLump ("ANIMDEFS", &lastlump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(lump, "ANIMDEFS");
|
FScanner sc(lump);
|
||||||
|
|
||||||
while (sc.GetString ())
|
while (sc.GetString ())
|
||||||
{
|
{
|
||||||
|
|
|
@ -1103,7 +1103,7 @@ class FPlayerSkin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
char name[17]; // 16 chars + NULL
|
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 gender; // This skin's gender (not really used)
|
||||||
BYTE range0start;
|
BYTE range0start;
|
||||||
BYTE range0end;
|
BYTE range0end;
|
||||||
|
|
|
@ -453,7 +453,7 @@ void R_InitSkins (void)
|
||||||
sndlumps[j] = -1;
|
sndlumps[j] = -1;
|
||||||
skins[i].namespc = Wads.GetLumpNamespace (base);
|
skins[i].namespc = Wads.GetLumpNamespace (base);
|
||||||
|
|
||||||
FScanner sc(base, "S_SKIN");
|
FScanner sc(base);
|
||||||
intname = 0;
|
intname = 0;
|
||||||
crouchname = 0;
|
crouchname = 0;
|
||||||
|
|
||||||
|
@ -501,6 +501,7 @@ void R_InitSkins (void)
|
||||||
{
|
{
|
||||||
for (j = 2; j >= 0; j--)
|
for (j = 2; j >= 0; j--)
|
||||||
skins[i].face[j] = toupper (sc.String[j]);
|
skins[i].face[j] = toupper (sc.String[j]);
|
||||||
|
skins[i].face[3] = '\0';
|
||||||
}
|
}
|
||||||
else if (0 == stricmp (key, "gender"))
|
else if (0 == stricmp (key, "gender"))
|
||||||
{
|
{
|
||||||
|
@ -886,11 +887,20 @@ void R_InitSprites ()
|
||||||
for (i = 0; i < PlayerClasses.Size (); i++)
|
for (i = 0; i < PlayerClasses.Size (); i++)
|
||||||
{
|
{
|
||||||
const PClass *basetype = PlayerClasses[i].Type;
|
const PClass *basetype = PlayerClasses[i].Type;
|
||||||
|
const char *pclassface = basetype->Meta.GetMetaString (APMETA_Face);
|
||||||
|
|
||||||
strcpy (skins[i].name, "Base");
|
strcpy (skins[i].name, "Base");
|
||||||
skins[i].face[0] = 'S';
|
if (strcmp(pclassface, "None") == 0)
|
||||||
skins[i].face[1] = 'T';
|
{
|
||||||
skins[i].face[2] = 'F';
|
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].range0start = basetype->Meta.GetMetaInt (APMETA_ColorRange) & 255;
|
||||||
skins[i].range0end = basetype->Meta.GetMetaInt (APMETA_ColorRange) >> 8;
|
skins[i].range0end = basetype->Meta.GetMetaInt (APMETA_ColorRange) >> 8;
|
||||||
skins[i].Scale = GetDefaultByType (basetype)->scaleX;
|
skins[i].Scale = GetDefaultByType (basetype)->scaleX;
|
||||||
|
|
|
@ -561,7 +561,6 @@ int S_AddPlayerSound (const char *pclass, int gender, int refid,
|
||||||
if (lumpname)
|
if (lumpname)
|
||||||
{
|
{
|
||||||
lump = Wads.CheckNumForFullName (lumpname, true, ns_sounds);
|
lump = Wads.CheckNumForFullName (lumpname, true, ns_sounds);
|
||||||
if (lump == -1) lump = Wads.CheckNumForName (lumpname, ns_sounds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_AddPlayerSound (pclass, gender, refid, lump);
|
return S_AddPlayerSound (pclass, gender, refid, lump);
|
||||||
|
@ -895,7 +894,7 @@ static void S_AddSNDINFO (int lump)
|
||||||
bool skipToEndIf;
|
bool skipToEndIf;
|
||||||
TArray<WORD> list;
|
TArray<WORD> list;
|
||||||
|
|
||||||
FScanner sc(lump, "SNDINFO");
|
FScanner sc(lump);
|
||||||
skipToEndIf = false;
|
skipToEndIf = false;
|
||||||
|
|
||||||
while (sc.GetString ())
|
while (sc.GetString ())
|
||||||
|
|
|
@ -465,7 +465,7 @@ FArchive &operator<< (FArchive &arc, ReverbContainer *&env)
|
||||||
return arc;
|
return arc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ReadEAX (int lump, const char *lumpname)
|
static void ReadEAX (int lump)
|
||||||
{
|
{
|
||||||
FScanner sc;
|
FScanner sc;
|
||||||
const ReverbContainer *def;
|
const ReverbContainer *def;
|
||||||
|
@ -476,7 +476,7 @@ static void ReadEAX (int lump, const char *lumpname)
|
||||||
bool inited[NUM_EAX_FIELDS];
|
bool inited[NUM_EAX_FIELDS];
|
||||||
BYTE bools[32];
|
BYTE bools[32];
|
||||||
|
|
||||||
sc.OpenLumpNum(lump, lumpname);
|
sc.OpenLumpNum(lump);
|
||||||
while (sc.GetString ())
|
while (sc.GetString ())
|
||||||
{
|
{
|
||||||
name = copystring (sc.String);
|
name = copystring (sc.String);
|
||||||
|
@ -576,7 +576,7 @@ void S_ParseSndEax ()
|
||||||
|
|
||||||
while ((lump = Wads.FindLump ("SNDEAX", &lastlump)) != -1)
|
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++)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (seq == Sequences.Size())
|
if (seq == Sequences.Size())
|
||||||
|
@ -499,7 +499,7 @@ void S_ParseSndSeq (int levellump)
|
||||||
lump = levellump;
|
lump = levellump;
|
||||||
levellump = -2;
|
levellump = -2;
|
||||||
}
|
}
|
||||||
FScanner sc(lump, "SNDSEQ");
|
FScanner sc(lump);
|
||||||
while (sc.GetString ())
|
while (sc.GetString ())
|
||||||
{
|
{
|
||||||
bool bDoorSound = false;
|
bool bDoorSound = false;
|
||||||
|
@ -514,7 +514,7 @@ void S_ParseSndSeq (int levellump)
|
||||||
seqtype = sc.String[0];
|
seqtype = sc.String[0];
|
||||||
for (curseq = 0; curseq < (int)Sequences.Size(); curseq++)
|
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]);
|
M_Free (Sequences[curseq]);
|
||||||
Sequences[curseq] = NULL;
|
Sequences[curseq] = NULL;
|
||||||
|
@ -684,6 +684,10 @@ void S_ParseSndSeq (int levellump)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (curseq > 0)
|
||||||
|
{
|
||||||
|
sc.ScriptError("End of file encountered before the final sequence ended.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameinfo.gametype == GAME_Hexen)
|
if (gameinfo.gametype == GAME_Hexen)
|
||||||
|
@ -883,7 +887,7 @@ static int FindSequence (FName seqname)
|
||||||
|
|
||||||
for (i = Sequences.Size(); i-- > 0; )
|
for (i = Sequences.Size(); i-- > 0; )
|
||||||
{
|
{
|
||||||
if (seqname == Sequences[i]->SeqName)
|
if (Sequences[i] != NULL && seqname == Sequences[i]->SeqName)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,7 +379,7 @@ void S_Start ()
|
||||||
if (*LocalSndInfo)
|
if (*LocalSndInfo)
|
||||||
{
|
{
|
||||||
// Now parse the local SNDINFO
|
// Now parse the local SNDINFO
|
||||||
int j = Wads.CheckNumForName(LocalSndInfo);
|
int j = Wads.CheckNumForFullName(LocalSndInfo, true);
|
||||||
if (j>=0) S_AddLocalSndInfo(j);
|
if (j>=0) S_AddLocalSndInfo(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +392,7 @@ void S_Start ()
|
||||||
}
|
}
|
||||||
if (parse_ss)
|
if (parse_ss)
|
||||||
{
|
{
|
||||||
S_ParseSndSeq(*LocalSndSeq? Wads.CheckNumForName(LocalSndSeq) : -1);
|
S_ParseSndSeq(*LocalSndSeq? Wads.CheckNumForFullName(LocalSndSeq, true) : -1);
|
||||||
}
|
}
|
||||||
else
|
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
|
// If this sound doesn't like playing near itself, don't play it if
|
||||||
// that's what would happen.
|
// 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;
|
return;
|
||||||
|
|
||||||
// Make sure the sound is loaded.
|
// 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;
|
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);
|
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 ();
|
Close ();
|
||||||
{
|
{
|
||||||
FMemLump mem = Wads.ReadLump(lump);
|
FMemLump mem = Wads.ReadLump(lump);
|
||||||
ScriptBuffer = mem.GetString();
|
ScriptBuffer = mem.GetString();
|
||||||
}
|
}
|
||||||
ScriptName = name;
|
ScriptName = Wads.GetLumpFullPath(lump);
|
||||||
PrepareScript ();
|
PrepareScript ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ public:
|
||||||
// Methods ------------------------------------------------------
|
// Methods ------------------------------------------------------
|
||||||
FScanner();
|
FScanner();
|
||||||
FScanner(const FScanner &other);
|
FScanner(const FScanner &other);
|
||||||
FScanner(int lumpnum, const char *name);
|
FScanner(int lumpnum);
|
||||||
~FScanner();
|
~FScanner();
|
||||||
|
|
||||||
FScanner &operator=(const FScanner &other);
|
FScanner &operator=(const FScanner &other);
|
||||||
|
@ -21,7 +21,7 @@ public:
|
||||||
void Open(const char *lumpname);
|
void Open(const char *lumpname);
|
||||||
void OpenFile(const char *filename);
|
void OpenFile(const char *filename);
|
||||||
void OpenMem(const char *name, char *buffer, int size);
|
void OpenMem(const char *name, char *buffer, int size);
|
||||||
void OpenLumpNum(int lump, const char *name);
|
void OpenLumpNum(int lump);
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
void SetCMode(bool cmode);
|
void SetCMode(bool cmode);
|
||||||
|
|
|
@ -1191,7 +1191,7 @@ FMOD_MODE FMODSoundRenderer::SetChanHeadSettings(FMOD::Channel *chan, sfxinfo_t
|
||||||
{
|
{
|
||||||
return oldmode;
|
return oldmode;
|
||||||
}
|
}
|
||||||
double cpos[3];
|
float cpos[3];
|
||||||
cpos[0] = FIXED2FLOAT(players[consoleplayer].camera->x);
|
cpos[0] = FIXED2FLOAT(players[consoleplayer].camera->x);
|
||||||
cpos[2] = FIXED2FLOAT(players[consoleplayer].camera->y);
|
cpos[2] = FIXED2FLOAT(players[consoleplayer].camera->y);
|
||||||
cpos[1] = FIXED2FLOAT(players[consoleplayer].camera->z);
|
cpos[1] = FIXED2FLOAT(players[consoleplayer].camera->z);
|
||||||
|
@ -1226,11 +1226,11 @@ FMOD_MODE FMODSoundRenderer::SetChanHeadSettings(FMOD::Channel *chan, sfxinfo_t
|
||||||
return oldmode;
|
return oldmode;
|
||||||
}
|
}
|
||||||
else if (cpos[0] == pos[0] && cpos[1] == pos[1] && cpos[2] == pos[2])
|
else if (cpos[0] == pos[0] && cpos[1] == pos[1] && cpos[2] == pos[2])
|
||||||
{
|
{ // Head relative
|
||||||
pos[2] = pos[1] = pos[0] = 0;
|
return (oldmode & ~FMOD_3D) | FMOD_2D;
|
||||||
return (oldmode & ~FMOD_3D_WORLDRELATIVE) | FMOD_3D_HEADRELATIVE;
|
|
||||||
}
|
}
|
||||||
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;
|
exinfo.length = size;
|
||||||
}
|
}
|
||||||
result = Sys->createSound((char *)sfxstart, samplemode, &exinfo, &sample);
|
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)
|
if (result != FMOD_OK)
|
||||||
{
|
{
|
||||||
DPrintf("Failed to allocate sample: %d\n", result);
|
DPrintf("Failed to allocate sample: Error %d\n", result);
|
||||||
errcount++;
|
errcount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,11 @@ FString MusInfo::GetStats()
|
||||||
return "No stats available for this song";
|
return "No stats available for this song";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MusInfo *MusInfo::GetOPLDumper(const char *filename)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void I_InitMusic (void)
|
void I_InitMusic (void)
|
||||||
{
|
{
|
||||||
static bool setatterm = false;
|
static bool setatterm = false;
|
||||||
|
@ -304,7 +309,6 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le
|
||||||
/* MUS are played as:
|
/* MUS are played as:
|
||||||
- OPL:
|
- OPL:
|
||||||
- if explicitly selected by $mididevice
|
- 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
|
- when snd_mididevice is -3 and no midi device is set for the song
|
||||||
|
|
||||||
Timidity:
|
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
|
- 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
|
- 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))
|
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
|
#ifdef _WIN32
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
{
|
{
|
||||||
info = new MUSSong2 (file, musiccache, len);
|
info = new MUSSong2 (file, musiccache, len, false);
|
||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
}
|
}
|
||||||
|
@ -384,7 +388,6 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le
|
||||||
/* MIDI are played as:
|
/* MIDI are played as:
|
||||||
OPL:
|
OPL:
|
||||||
- if explicitly selected by $mididevice
|
- 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
|
- when snd_mididevice is -3 and no midi device is set for the song
|
||||||
|
|
||||||
Timidity:
|
Timidity:
|
||||||
|
@ -422,8 +425,11 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le
|
||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
}
|
}
|
||||||
// Check for RDosPlay raw OPL format
|
// Check for various raw OPL formats
|
||||||
else if (id == MAKE_ID('R','A','W','A') && len >= 12)
|
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];
|
DWORD fullsig[2];
|
||||||
|
|
||||||
|
@ -441,30 +447,9 @@ void *I_RegisterSong (const char *filename, char *musiccache, int offset, int le
|
||||||
memcpy(fullsig, musiccache, 8);
|
memcpy(fullsig, musiccache, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fullsig[1] == MAKE_ID('D','A','T','A'))
|
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')) ||
|
||||||
info = new OPLMUSSong (file, musiccache, len);
|
(fullsig[0] == MAKE_ID('A','D','L','I') && (fullsig[1] & MAKE_ID(255,255,0,0)) == MAKE_ID('B',1,0,0)))
|
||||||
}
|
|
||||||
}
|
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
info = new OPLMUSSong (file, musiccache, len);
|
info = new OPLMUSSong (file, musiccache, len);
|
||||||
}
|
}
|
||||||
|
@ -597,3 +582,40 @@ ADD_STAT(music)
|
||||||
}
|
}
|
||||||
return "No song playing";
|
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 bool SetPosition (int order);
|
||||||
virtual void Update();
|
virtual void Update();
|
||||||
virtual FString GetStats();
|
virtual FString GetStats();
|
||||||
|
virtual MusInfo *GetOPLDumper(const char *filename);
|
||||||
|
|
||||||
enum EState
|
enum EState
|
||||||
{
|
{
|
||||||
|
@ -152,7 +153,7 @@ protected:
|
||||||
|
|
||||||
// OPL implementation of a MIDI output device -------------------------------
|
// OPL implementation of a MIDI output device -------------------------------
|
||||||
|
|
||||||
class OPLMIDIDevice : public MIDIDevice, OPLmusicBlock
|
class OPLMIDIDevice : public MIDIDevice, protected OPLmusicBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OPLMIDIDevice();
|
OPLMIDIDevice();
|
||||||
|
@ -191,6 +192,17 @@ protected:
|
||||||
DWORD Position;
|
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 ------------------------------
|
// Base class for streaming MUS and MIDI files ------------------------------
|
||||||
|
|
||||||
class MIDIStreamer : public MusInfo
|
class MIDIStreamer : public MusInfo
|
||||||
|
@ -210,13 +222,15 @@ public:
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void Callback(unsigned int uMsg, void *userdata, DWORD dwParam1, DWORD dwParam2);
|
MIDIStreamer(const char *dumpname);
|
||||||
|
|
||||||
void OutputVolume (DWORD volume);
|
void OutputVolume (DWORD volume);
|
||||||
int FillBuffer(int buffer_num, int max_events, DWORD max_time);
|
int FillBuffer(int buffer_num, int max_events, DWORD max_time);
|
||||||
bool ServiceEvent();
|
bool ServiceEvent();
|
||||||
int VolumeControllerChange(int channel, int volume);
|
int VolumeControllerChange(int channel, int volume);
|
||||||
|
|
||||||
|
static void Callback(unsigned int uMsg, void *userdata, DWORD dwParam1, DWORD dwParam2);
|
||||||
|
|
||||||
// Virtuals for subclasses to override
|
// Virtuals for subclasses to override
|
||||||
virtual void CheckCaps();
|
virtual void CheckCaps();
|
||||||
virtual void DoInitialSetup() = 0;
|
virtual void DoInitialSetup() = 0;
|
||||||
|
@ -261,6 +275,7 @@ protected:
|
||||||
DWORD Volume;
|
DWORD Volume;
|
||||||
bool UseOPLDevice;
|
bool UseOPLDevice;
|
||||||
bool CallbackIsThreaded;
|
bool CallbackIsThreaded;
|
||||||
|
FString DumpFilename;
|
||||||
};
|
};
|
||||||
|
|
||||||
// MUS file played with a MIDI stream ---------------------------------------
|
// MUS file played with a MIDI stream ---------------------------------------
|
||||||
|
@ -268,10 +283,14 @@ protected:
|
||||||
class MUSSong2 : public MIDIStreamer
|
class MUSSong2 : public MIDIStreamer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MUSSong2 (FILE *file, char *musiccache, int length);
|
MUSSong2(FILE *file, char *musiccache, int length, bool opl);
|
||||||
~MUSSong2 ();
|
~MUSSong2();
|
||||||
|
|
||||||
|
MusInfo *GetOPLDumper(const char *filename);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
MUSSong2(const MUSSong2 *original, const char *filename); //OPL dump constructor
|
||||||
|
|
||||||
void DoInitialSetup();
|
void DoInitialSetup();
|
||||||
void DoRestart();
|
void DoRestart();
|
||||||
bool CheckDone();
|
bool CheckDone();
|
||||||
|
@ -288,10 +307,14 @@ protected:
|
||||||
class MIDISong2 : public MIDIStreamer
|
class MIDISong2 : public MIDIStreamer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MIDISong2 (FILE *file, char *musiccache, int length, bool opl);
|
MIDISong2(FILE *file, char *musiccache, int length, bool opl);
|
||||||
~MIDISong2 ();
|
~MIDISong2();
|
||||||
|
|
||||||
|
MusInfo *GetOPLDumper(const char *filename);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
MIDISong2(const MIDISong2 *original, const char *filename); // OPL dump constructor
|
||||||
|
|
||||||
void CheckCaps();
|
void CheckCaps();
|
||||||
void DoInitialSetup();
|
void DoInitialSetup();
|
||||||
void DoRestart();
|
void DoRestart();
|
||||||
|
@ -307,6 +330,7 @@ protected:
|
||||||
void SetTempo(int new_tempo);
|
void SetTempo(int new_tempo);
|
||||||
|
|
||||||
BYTE *MusHeader;
|
BYTE *MusHeader;
|
||||||
|
int SongLen;
|
||||||
TrackInfo *Tracks;
|
TrackInfo *Tracks;
|
||||||
TrackInfo *TrackDue;
|
TrackInfo *TrackDue;
|
||||||
int NumTracks;
|
int NumTracks;
|
||||||
|
@ -381,19 +405,29 @@ protected:
|
||||||
class OPLMUSSong : public StreamSong
|
class OPLMUSSong : public StreamSong
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OPLMUSSong (FILE *file, char * musiccache, int length);
|
OPLMUSSong (FILE *file, char *musiccache, int length);
|
||||||
~OPLMUSSong ();
|
~OPLMUSSong ();
|
||||||
void Play (bool looping);
|
void Play (bool looping);
|
||||||
bool IsPlaying ();
|
bool IsPlaying ();
|
||||||
bool IsValid () const;
|
bool IsValid () const;
|
||||||
void ResetChips ();
|
void ResetChips ();
|
||||||
|
MusInfo *GetOPLDumper(const char *filename);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
OPLMUSSong(const OPLMUSSong *original, const char *filename); // OPL dump constructor
|
||||||
|
|
||||||
static bool FillStream (SoundStream *stream, void *buff, int len, void *userdata);
|
static bool FillStream (SoundStream *stream, void *buff, int len, void *userdata);
|
||||||
|
|
||||||
OPLmusicFile *Music;
|
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 -----------------------
|
// CD track/disk played through the multimedia system -----------------------
|
||||||
|
|
||||||
class CDSong : public MusInfo
|
class CDSong : public MusInfo
|
||||||
|
@ -430,4 +464,3 @@ extern MusInfo *currSong;
|
||||||
extern int nomusic;
|
extern int nomusic;
|
||||||
|
|
||||||
EXTERN_CVAR (Float, snd_musicvolume)
|
EXTERN_CVAR (Float, snd_musicvolume)
|
||||||
EXTERN_CVAR (Bool, opl_enable)
|
|
||||||
|
|
|
@ -44,8 +44,6 @@
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// 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.
|
// Used by SendCommand to check for unexpected end-of-track conditions.
|
||||||
#define CHECK_FINISHED \
|
#define CHECK_FINISHED \
|
||||||
if (track->TrackP >= track->MaxTrackP) \
|
if (track->TrackP >= track->MaxTrackP) \
|
||||||
|
@ -115,6 +113,7 @@ MIDISong2::MIDISong2 (FILE *file, char *musiccache, int len, bool opl)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
MusHeader = new BYTE[len];
|
MusHeader = new BYTE[len];
|
||||||
|
SongLen = len;
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
{
|
{
|
||||||
if (fread(MusHeader, 1, len, file) != (size_t)len)
|
if (fread(MusHeader, 1, len, file) != (size_t)len)
|
||||||
|
@ -754,3 +753,43 @@ void MIDISong2::SetTempo(int new_tempo)
|
||||||
Tempo = 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)
|
MIDIStreamer::MIDIStreamer(bool opl)
|
||||||
: MIDI(0),
|
:
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
PlayerThread(0), ExitEvent(0), BufferDoneEvent(0),
|
PlayerThread(0), ExitEvent(0), BufferDoneEvent(0),
|
||||||
#endif
|
#endif
|
||||||
Division(0), InitialTempo(500000), UseOPLDevice(opl)
|
MIDI(0), Division(0), InitialTempo(500000), UseOPLDevice(opl)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
BufferDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
BufferDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
@ -91,6 +91,25 @@ MIDIStreamer::MIDIStreamer(bool opl)
|
||||||
#endif
|
#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
|
// MIDIStreamer Destructor
|
||||||
|
@ -163,7 +182,7 @@ void MIDIStreamer::CheckCaps()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void MIDIStreamer::Play (bool looping)
|
void MIDIStreamer::Play(bool looping)
|
||||||
{
|
{
|
||||||
DWORD tid;
|
DWORD tid;
|
||||||
|
|
||||||
|
@ -175,6 +194,11 @@ void MIDIStreamer::Play (bool looping)
|
||||||
InitialPlayback = true;
|
InitialPlayback = true;
|
||||||
|
|
||||||
assert(MIDI == NULL);
|
assert(MIDI == NULL);
|
||||||
|
if (DumpFilename.IsNotEmpty())
|
||||||
|
{
|
||||||
|
MIDI = new OPLDumperMIDIDevice(DumpFilename);
|
||||||
|
}
|
||||||
|
else
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!UseOPLDevice)
|
if (!UseOPLDevice)
|
||||||
{
|
{
|
||||||
|
@ -188,7 +212,7 @@ void MIDIStreamer::Play (bool looping)
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
assert(MIDI->NeedThreadedCallback() == false);
|
assert(MIDI->NeedThreadedCallback() == false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (0 != MIDI->Open(Callback, this))
|
if (0 != MIDI->Open(Callback, this))
|
||||||
{
|
{
|
||||||
|
@ -281,7 +305,7 @@ void MIDIStreamer::Play (bool looping)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void MIDIStreamer::Pause ()
|
void MIDIStreamer::Pause()
|
||||||
{
|
{
|
||||||
if (m_Status == STATE_Playing)
|
if (m_Status == STATE_Playing)
|
||||||
{
|
{
|
||||||
|
@ -302,7 +326,7 @@ void MIDIStreamer::Pause ()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void MIDIStreamer::Resume ()
|
void MIDIStreamer::Resume()
|
||||||
{
|
{
|
||||||
if (m_Status == STATE_Paused)
|
if (m_Status == STATE_Paused)
|
||||||
{
|
{
|
||||||
|
@ -322,7 +346,7 @@ void MIDIStreamer::Resume ()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void MIDIStreamer::Stop ()
|
void MIDIStreamer::Stop()
|
||||||
{
|
{
|
||||||
EndQueued = 2;
|
EndQueued = 2;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -355,7 +379,7 @@ void MIDIStreamer::Stop ()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool MIDIStreamer::IsPlaying ()
|
bool MIDIStreamer::IsPlaying()
|
||||||
{
|
{
|
||||||
return m_Status != STATE_Stopped;
|
return m_Status != STATE_Stopped;
|
||||||
}
|
}
|
||||||
|
@ -369,7 +393,7 @@ bool MIDIStreamer::IsPlaying ()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void MIDIStreamer::MusicVolumeChanged ()
|
void MIDIStreamer::MusicVolumeChanged()
|
||||||
{
|
{
|
||||||
if (MIDI->FakeVolume())
|
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 ------------------------------------------------------------
|
// HEADER FILES ------------------------------------------------------------
|
||||||
|
|
||||||
#include "i_musicinterns.h"
|
#include "i_musicinterns.h"
|
||||||
|
@ -52,8 +50,6 @@
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern UINT mididevice;
|
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
static const BYTE CtrlTranslate[15] =
|
static const BYTE CtrlTranslate[15] =
|
||||||
|
@ -88,13 +84,15 @@ static const BYTE CtrlTranslate[15] =
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
MUSSong2::MUSSong2 (FILE *file, char *musiccache, int len)
|
MUSSong2::MUSSong2 (FILE *file, char *musiccache, int len, bool opl)
|
||||||
: MIDIStreamer(false), MusHeader(0), MusBuffer(0)
|
: MIDIStreamer(opl), MusHeader(0), MusBuffer(0)
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
if (ExitEvent == NULL)
|
if (ExitEvent == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
MusHeader = (MUSHeader *)new BYTE[len];
|
MusHeader = (MUSHeader *)new BYTE[len];
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
|
@ -304,4 +302,32 @@ end:
|
||||||
}
|
}
|
||||||
return events;
|
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"
|
#include "i_musicinterns.h"
|
||||||
|
|
||||||
CVAR (Bool, opl_enable, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|
||||||
|
|
||||||
static bool OPL_Active;
|
static bool OPL_Active;
|
||||||
|
|
||||||
CUSTOM_CVAR (Bool, opl_onechip, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
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)
|
OPLMUSSong::OPLMUSSong (FILE *file, char *musiccache, int len)
|
||||||
{
|
{
|
||||||
int samples = int(OPL_SAMPLE_RATE / 14);
|
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,
|
m_Stream = GSnd->CreateStream (FillStream, samples*4,
|
||||||
SoundStream::Mono | SoundStream::Float, int(OPL_SAMPLE_RATE), this);
|
SoundStream::Mono | SoundStream::Float, int(OPL_SAMPLE_RATE), this);
|
||||||
|
@ -63,7 +60,7 @@ void OPLMUSSong::Play (bool looping)
|
||||||
Music->SetLooping (looping);
|
Music->SetLooping (looping);
|
||||||
Music->Restart ();
|
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;
|
m_Status = STATE_Playing;
|
||||||
}
|
}
|
||||||
|
@ -74,3 +71,24 @@ bool OPLMUSSong::FillStream (SoundStream *stream, void *buff, int len, void *use
|
||||||
OPLMUSSong *song = (OPLMUSSong *)userdata;
|
OPLMUSSong *song = (OPLMUSSong *)userdata;
|
||||||
return song->Music->ServiceStream (buff, len);
|
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;
|
code |= orMask;
|
||||||
|
|
||||||
FScanner sc(lumpnum, "LANGUAGE");
|
FScanner sc(lumpnum);
|
||||||
sc.SetCMode (true);
|
sc.SetCMode (true);
|
||||||
while (sc.GetString ())
|
while (sc.GetString ())
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
// This file was automatically generated by the
|
// This file was automatically generated by the
|
||||||
// updaterevision tool. Do not edit by hand.
|
// updaterevision tool. Do not edit by hand.
|
||||||
|
|
||||||
#define ZD_SVN_REVISION_STRING "871"
|
#define ZD_SVN_REVISION_STRING "882"
|
||||||
#define ZD_SVN_REVISION_NUMBER 871
|
#define ZD_SVN_REVISION_NUMBER 882
|
||||||
|
|
|
@ -84,7 +84,7 @@ void TEAMINFO_Init ()
|
||||||
|
|
||||||
while ((lump = Wads.FindLump ("TEAMINFO", &lastlump)) != -1)
|
while ((lump = Wads.FindLump ("TEAMINFO", &lastlump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(lump, "TEAMINFO");
|
FScanner sc(lump);
|
||||||
while (sc.GetString ())
|
while (sc.GetString ())
|
||||||
{
|
{
|
||||||
if (sc.Compare("CLEARTEAMS"))
|
if (sc.Compare("CLEARTEAMS"))
|
||||||
|
|
|
@ -508,7 +508,7 @@ void FTextureManager::LoadHiresTex(int wadnum)
|
||||||
{
|
{
|
||||||
if (Wads.GetLumpFile(remapLump) == wadnum)
|
if (Wads.GetLumpFile(remapLump) == wadnum)
|
||||||
{
|
{
|
||||||
FScanner sc(remapLump, "HIRESTEX");
|
FScanner sc(remapLump);
|
||||||
while (sc.GetString())
|
while (sc.GetString())
|
||||||
{
|
{
|
||||||
if (sc.Compare("remap")) // remap an existing texture
|
if (sc.Compare("remap")) // remap an existing texture
|
||||||
|
|
|
@ -1145,7 +1145,7 @@ void A_CustomPunch (AActor *self)
|
||||||
PuffType = PClass::FindClass(PuffTypeName);
|
PuffType = PClass::FindClass(PuffTypeName);
|
||||||
if (!PuffType) PuffType = PClass::FindClass(NAME_BulletPuff);
|
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
|
// turn to face target
|
||||||
if (linetarget)
|
if (linetarget)
|
||||||
|
|
|
@ -150,7 +150,7 @@ void LoadDecorations ()
|
||||||
lastlump = 0;
|
lastlump = 0;
|
||||||
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
|
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(lump, Wads.GetLumpFullName(lump));
|
FScanner sc(lump);
|
||||||
ParseDecorate (sc);
|
ParseDecorate (sc);
|
||||||
}
|
}
|
||||||
FinishThingdef();
|
FinishThingdef();
|
||||||
|
|
|
@ -235,6 +235,7 @@ static flagdef ActorFlags[]=
|
||||||
DEFINE_FLAG(MF5, NEVERRESPAWN, AActor, flags5),
|
DEFINE_FLAG(MF5, NEVERRESPAWN, AActor, flags5),
|
||||||
DEFINE_FLAG(MF5, DONTRIP, AActor, flags5),
|
DEFINE_FLAG(MF5, DONTRIP, AActor, flags5),
|
||||||
DEFINE_FLAG(MF5, NOINFIGHTING, AActor, flags5),
|
DEFINE_FLAG(MF5, NOINFIGHTING, AActor, flags5),
|
||||||
|
DEFINE_FLAG(MF5, NOINTERACTION, AActor, flags5),
|
||||||
|
|
||||||
// Effect flags
|
// Effect flags
|
||||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
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);
|
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.crouchsprite", (apf)PlayerCrouchSprite, RUNTIME_CLASS(APlayerPawn) },
|
||||||
{ "player.damagescreencolor", (apf)PlayerDmgScreenColor, RUNTIME_CLASS(APlayerPawn) },
|
{ "player.damagescreencolor", (apf)PlayerDmgScreenColor, RUNTIME_CLASS(APlayerPawn) },
|
||||||
{ "player.displayname", (apf)PlayerDisplayName, 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.forwardmove", (apf)PlayerForwardMove, RUNTIME_CLASS(APlayerPawn) },
|
||||||
{ "player.healradiustype", (apf)PlayerHealRadius, RUNTIME_CLASS(APlayerPawn) },
|
{ "player.healradiustype", (apf)PlayerHealRadius, RUNTIME_CLASS(APlayerPawn) },
|
||||||
{ "player.hexenarmor", (apf)PlayerHexenArmor, RUNTIME_CLASS(APlayerPawn) },
|
{ "player.hexenarmor", (apf)PlayerHexenArmor, RUNTIME_CLASS(APlayerPawn) },
|
||||||
|
|
|
@ -218,12 +218,6 @@ FFont *V_GetFont(const char *name)
|
||||||
int lump = -1;
|
int lump = -1;
|
||||||
|
|
||||||
lump = Wads.CheckNumForFullName(name, true);
|
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)
|
if (lump != -1)
|
||||||
{
|
{
|
||||||
|
@ -293,6 +287,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
|
||||||
double *luminosity;
|
double *luminosity;
|
||||||
int maxyoffs;
|
int maxyoffs;
|
||||||
bool doomtemplate = gameinfo.gametype == GAME_Doom ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
|
bool doomtemplate = gameinfo.gametype == GAME_Doom ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
|
||||||
|
bool stcfn121 = false;
|
||||||
|
|
||||||
Chars = new CharData[count];
|
Chars = new CharData[count];
|
||||||
charlumps = new int[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);
|
lump = Wads.CheckNumForName (buffer, ns_graphics);
|
||||||
if (doomtemplate && lump >= 0 && i + start == 121)
|
if (doomtemplate && lump >= 0 && i + start == 121)
|
||||||
{ // HACKHACK: Don't load STCFN121 in doom(2), because
|
{ // 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
|
// 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.
|
// provide STCFN120 (x) and STCFN122 (z) for STCFN121 to load.
|
||||||
if (Wads.CheckNumForName ("STCFN120", ns_graphics) == -1 ||
|
if (Wads.CheckNumForName ("STCFN120", ns_graphics) == -1 ||
|
||||||
Wads.CheckNumForName ("STCFN122", 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;
|
lump = -1;
|
||||||
|
stcfn121 = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
charlumps[i] = lump;
|
if (lump != -1 || i != 124-start || !stcfn121)
|
||||||
|
charlumps[i] = lump;
|
||||||
|
|
||||||
if (lump >= 0)
|
if (lump >= 0)
|
||||||
{
|
{
|
||||||
FTexture *pic = TexMan[buffer];
|
FTexture *pic = TexMan[buffer];
|
||||||
|
@ -1631,7 +1631,7 @@ void V_InitCustomFonts()
|
||||||
|
|
||||||
while ((llump = Wads.FindLump ("FONTDEFS", &lastlump)) != -1)
|
while ((llump = Wads.FindLump ("FONTDEFS", &lastlump)) != -1)
|
||||||
{
|
{
|
||||||
sc.OpenLumpNum(llump, "FONTDEFS");
|
sc.OpenLumpNum(llump);
|
||||||
while (sc.GetString())
|
while (sc.GetString())
|
||||||
{
|
{
|
||||||
memset (lumplist, -1, sizeof(lumplist));
|
memset (lumplist, -1, sizeof(lumplist));
|
||||||
|
@ -1691,7 +1691,7 @@ void V_InitCustomFonts()
|
||||||
if (format == 1) goto wrong;
|
if (format == 1) goto wrong;
|
||||||
int *p = &lumplist[*(unsigned char*)sc.String];
|
int *p = &lumplist[*(unsigned char*)sc.String];
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
*p = Wads.CheckNumForName (sc.String);
|
*p = Wads.CheckNumForFullName (sc.String, true);
|
||||||
format=2;
|
format=2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1759,7 +1759,7 @@ void V_InitFontColors ()
|
||||||
|
|
||||||
while ((lump = Wads.FindLump ("TEXTCOLO", &lastlump)) != -1)
|
while ((lump = Wads.FindLump ("TEXTCOLO", &lastlump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(lump, "textcolors.txt");
|
FScanner sc(lump);
|
||||||
while (sc.GetString())
|
while (sc.GetString())
|
||||||
{
|
{
|
||||||
names.Clear();
|
names.Clear();
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
// SAVESIG should match SAVEVER.
|
// SAVESIG should match SAVEVER.
|
||||||
|
|
||||||
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
||||||
#define MINSAVEVER 854
|
#define MINSAVEVER 879
|
||||||
|
|
||||||
#if ZD_SVN_REVISION_NUMBER < MINSAVEVER
|
#if ZD_SVN_REVISION_NUMBER < MINSAVEVER
|
||||||
// Never write a savegame with a version lower than what we need
|
// 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;
|
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
|
// GetLumpNamespace
|
||||||
|
|
|
@ -206,6 +206,7 @@ public:
|
||||||
int GetLumpFlags (int lump); // Return the flags for this lump
|
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
|
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
|
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 GetLumpFile (int lump) const; // [RH] Returns wadnum for a specified lump
|
||||||
int GetLumpNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to
|
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
|
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
|
else
|
||||||
{
|
{
|
||||||
int lumpnum=Wads.GetNumForName(lumpname+1);
|
int lumpnum=Wads.CheckNumForFullName(lumpname+1, true);
|
||||||
if (lumpnum>=0)
|
if (lumpnum>=0)
|
||||||
{
|
{
|
||||||
FScanner sc(lumpnum,lumpname+1);
|
FScanner sc(lumpnum);
|
||||||
while (sc.GetString())
|
while (sc.GetString())
|
||||||
{
|
{
|
||||||
memset(&an,0,sizeof(an));
|
memset(&an,0,sizeof(an));
|
||||||
|
|
|
@ -2,7 +2,7 @@ ifeq (Windows_NT,$(OS))
|
||||||
WIN=1
|
WIN=1
|
||||||
WINCMD=1
|
WINCMD=1
|
||||||
endif
|
endif
|
||||||
ifeq (msys,$(OSTYPE))
|
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||||
WIN=1
|
WIN=1
|
||||||
WINCMD=0
|
WINCMD=0
|
||||||
endif
|
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,11 +1,10 @@
|
||||||
ifeq (Windows_NT,$(OS))
|
ifeq (Windows_NT,$(OS))
|
||||||
WIN=1
|
WIN=1
|
||||||
WINCMD=1
|
WINCMD=1
|
||||||
endif
|
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||||
ifeq (msys,$(OSTYPE))
|
WINCMD=0
|
||||||
WIN=1
|
endif
|
||||||
WINCMD=0
|
endif
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq (1,$(WIN))
|
ifeq (1,$(WIN))
|
||||||
EXE = makewad.exe
|
EXE = makewad.exe
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
ifeq (Windows_NT,$(OS))
|
ifeq (Windows_NT,$(OS))
|
||||||
WIN=1
|
WIN=1
|
||||||
WINCMD=1
|
WINCMD=1
|
||||||
endif
|
ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys)
|
||||||
ifeq (msys,$(OSTYPE))
|
WINCMD=0
|
||||||
WIN=1
|
endif
|
||||||
WINCMD=0
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (1,$(WIN))
|
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