3.0 beta 4

This commit is contained in:
Chris Danford
2002-07-11 19:02:26 +00:00
parent f8042bcc52
commit 82e52c1306
73 changed files with 1936 additions and 731 deletions
+475 -111
View File
@@ -35,48 +35,61 @@ Table of Contents
11. Questions, Bugs, Suggestions, and Help
12. The StepMania Editor
13. The .SM File Format
14. Building StepMania from CVS Source
15. Version History
14. Background Animations
15. The .CRS File Format
16. Building StepMania from CVS Source
17. Version History
************************************************************
1. About StepMania
************************************************************
StepMania game system is capable of playing many game types. Currently, it supports games Dance Dance Revolution and Pump It Up, with future support for EZ 2 Dancer, BeatMania, Guitar Freaks, DrumMania, Para Para Paradise and more.
StepMania game system is capable of playing many game types. Currently, it
supports games Dance Dance Revolution and Pump It Up, with future support for EZ
2 Dancer, BeatMania, Guitar Freaks, DrumMania, Para Para Paradise and more.
************************************************************
2. Minimum Requirements
************************************************************
* Windows 98, Windows ME, Windows 2000, or Windows XP.
* Required: Pentium II, Pentium III, Celeron, Athlon, or compatible processor, 266MHz minimum (400 MHz highly recommended).
* 64 MB of RAM.
* Video card that supports High Color (16-bit color) and has 16MB video RAM.
* DirectX 8.1 compatible video card with drivers.
* DirectX 8.1 compatible sound card with drivers.
* DivX 5 video codec (for movie visualizations).
* Windows 98, Windows ME, Windows 2000, or Windows XP
* Pentium II, Pentium III, Celeron, Athlon, or compatible processor, 266MHz
minimum (400 MHz highly recommended)
* 64 MB of RAM
* Video card that supports High Color (16-bit color) and has 16MB video RAM
* DirectX 8.1 compatible video card with drivers
* DirectX 8.1 compatible sound card with drivers
* DivX 5 video codec (for movie visualizations)
************************************************************
3. DirectX
************************************************************
DirectX 8.1 is required before installing StepMania. If DirectX 8.1 is not installed on your computer, the StepMania installer will display a warning and abort the installation.
DirectX 8.1 is required before installing StepMania. If DirectX 8.1 is not
installed on your computer, the StepMania installer will display a warning
and abort the installation.
************************************************************
4. Installation
************************************************************
To install StepMania, download the file stepmania3.exe to a known location on your hard drive, then double-click the file icon to begin the installation. The installer automatically remove an older version of the program if one is present. The default installation directory is 'C:\Program Files\StepMania'.
To install StepMania, download the file stepmania3.exe to a known location
on your hard drive, then double-click the file icon to begin the installation.
The installer automatically remove an older version of the program if one is
present. The default installation directory is 'C:\Program Files\StepMania'.
************************************************************
5. Controls
************************************************************
Use the "Config Key/Joy" option from the Title Menu to configure your keyboad or dance pad.
Use the "Config Key/Joy" option from the Title Menu to configure your
keyboad or dance pad.
Any time:
* F4 = toggle fullscreen
* F5 = toggle detail
* Tab = increase game speed 4x
* LShift = decrease game speed to 1/4x
In menus:
* Arrow keys navigate menus
@@ -85,12 +98,14 @@ In menus:
In gameplay:
* F11 = decrease offset
* F12 = increase offset
* Hold Escape = abort playing
************************************************************
6. How StepMania Loads Songs
************************************************************
All song files for a specific song (data file, music file, banner, background) must reside in a single folder. This folder must have the following path:
All song files for a specific song (data file, music file, banner, background)
must reside in a single folder. This folder must have the following path:
Songs/<group folder>/<song folder>/
@@ -100,44 +115,94 @@ For example, the song B4U may consist of the following files:
Songs/Dance Dance Revolution 4th Mix/B4U/b4u.mp3
Songs/Dance Dance Revolution 4th Mix/B4U/b4u-banner.png
Songs/Dance Dance Revolution 4th Mix/B4U/b4u.png
Songs/Dance Dance Revolution 4th Mix/B4U/b4u-movie.avi
StepMania supports the SM, DWI, and BMS song file formats.
If a song file does not specify a valid banner file, StepMania first looks
for a graphic in the song folder that contains the letters "banner". If that
search fails, StepMania will guess which image is most appropriate.
If a song file does not specify a valid background file, StepMania first looks
for a graphic in the song folder that contains the letters "bg" or "background".
If that search fails, StepMania will guess which image is most appropriate.
If a song file does not specify a valid CDTitle file, StepMania will look
for a graphic in the song folder that contains the letters "cdtitle". If that
search fails, StepMania will guess which image is most appropriate.
Also, for compatibility with DWI, if can reading CDTitles from the .\CDTitles
folder. Song makers are not encouraged to not use this feature and instead
should put the CDTitle graphic in the song folder. Having a separate CDTitles
folder breaks the principle that all files needed to play a song should reside
in the song folder.
If a song file does not specify a valid movie background file, StepMania will
look for a movie in the song folder that contains the letters "movie". If
that search fails, StepMania will use the first movie in the song folder.
************************************************************
7. Connecting Dance Pads
************************************************************
There are several devices that allow you to connect PlayStation dance pads to your PC.
There are several devices that allow you to connect PlayStation dance pads to
your PC.
* Not recommended: generic PlayStation->USB converter
Using a generic PlayStation->USB converter is not recommended to play any dancing game on the PC. The vast majority of these converters are not capable of registering simultaneous presses of Left+Right or Up+Down. This restriction will cause the player to miss many notes where two buttons must be hit simultaneously.
Using a generic PlayStation->USB converter is not recommended to play any
dancing game on the PC. The vast majority of these converters are not capable
of registering simultaneous presses of Left+Right or Up+Down. This
restriction will cause the player to miss many notes where two buttons must
be hit simultaneously.
* Highly Recommended: Special PlayStation->USB adaptor
There is just one brand of PlayStation->USB adaptor that functions perfectly with StepMania. These adaptors are available for purchase at the StepMania web site (www.stepmania.com) and through some importers (www.liksang.com). The adaptor is made by “Boom”, and it small and black with a detachable USB cable. These adaptors cost about $15 and allow you to attach one dance pad per adaptor. The primary advantage of these adaptors is that they do not require special drivers and require no configuring.
There is just one brand of PlayStation->USB adaptor that functions perfectly
with StepMania. These adaptors are available for purchase at the StepMania
web site (www.stepmania.com) and through some importers (www.liksang.com).
The adaptor is made by “Boom”, and it small and black with a detachable USB
cable. These adaptors cost about $15 and allow you to attach one dance pad
per adaptor. The primary advantage of these adaptors is that they do not
require special drivers and require no configuring.
* Semi-Recommended: PlayStation->Parallel adaptor
PlayStation->Parallel converters do not have the simultaneous button problem that USB converters do. The disadvantage of these adaptors is that home-made drivers are required to use these devices. These drivers are often finicky and incompatible with some sound cards. PlayStation->Parallel adaptors can be purchased from the StepMania web site or any importer.
PlayStation->Parallel converters do not have the simultaneous button problem
that USB converters do. The disadvantage of these adaptors is that home-made
drivers are required to use these devices. These drivers are often finicky
and incompatible with some sound cards. PlayStation->Parallel adaptors can
be purchased from the StepMania web site or any importer.
For Windows 98 and Windows Me users, the recommended driver is DirectPad Pro 5.0 for Win9x”. For Windows 2000 and Windows XP, the recommended drivers are NTPad XP 1.x. Both of these drivers can be downloaded from Aldos web site: http://www.aldostools.com/dpad.html
For Windows 98 and Windows Me users, the recommended driver is "DirectPad Pro
5.0 for Win9x". For Windows 2000 and Windows XP, the recommended drivers are
NTPad XP 1.x. Both of these drivers can be downloaded from Aldos web site:
http://www.aldostools.com/dpad.html
************************************************************
8. Compatibility Issues
************************************************************
Some video card/driver combinations have visual errors when running StepMania. If you experience any visual errors, please visit your video card manufacturer's web site and download the latest Direct3D 8.1 drivers. Below is a list of known issues that are thought to be video card driver bugs:
Some video card/driver combinations have visual errors when running StepMania.
If you experience any visual errors, please visit your video card manufacturer's
web site and download the latest Direct3D 8.1 drivers. Below is a list of known
issues that are thought to be video card driver bugs:
* S3 Savage family cards (e.g. Diamond Stealth)
Symptom: The right edge of some graphics appears "cut off".
Explanation: Drivers do not properly handle textures > 512x512, resulting in cropped textures. Please use the Low texture detail option to force texture to be 512x512 or smaller.
Explanation: Drivers do not properly handle textures > 512x512, resulting in
cropped textures. Please use the Low texture detail option to force texture to
be 512x512 or smaller.
* SiS cards
Symptom: Garbled fonts.
Explanation: Drivers have errors in handling texture coordinates. Only known solution is to upgrade drivers.
Explanation: Drivers have errors in handling texture coordinates. Only known
solution is to upgrade drivers.
* Any card older than two years
Symptom: Various graphical glitches.
Explanation: These problems are most often video card driver bugs. Please upgrade to the latest drivers, which will hopefully fix the errors.
Explanation: These problems are most often video card driver bugs. Please
upgrade to the latest drivers, which will hopefully fix the errors.
************************************************************
@@ -150,15 +215,21 @@ You need to download DirectX 8.1. http://www.microsoft.com/directx
* Music rates of over 100% do not work on my computer. Why?
Some very old sound cards do not support sound playback rates that are greater than the original sample rate. This problem is likely to be corrected by newer sound card drivers.
Some very old sound cards do not support sound playback rates that are greater
than the original sample rate. This problem is likely to be corrected by newer
sound card drivers.
* StepMania reports Direct3D Create Device failed.
* StepMania reports "Direct3D Create Device failed".
This error means that your video card or drivers do not support Direct3D 8. Download the latest drivers for your video card. If your video card is older than 2 or 3 years, Direct3D 8 drivers may not be available. Sorry.
This error means that your video card or drivers do not support Direct3D 8.
Download the latest drivers for your video card. If your video card is older
than 2 or 3 years, Direct3D 8 drivers may not be available. Sorry.
* Im looking to purchase a video card. What works well with StepMania?
Just about any video card manufactured in the last year will run StepMania flawlessly at 60 frames per second. I recommend any card with an nVidia GeForce chip or an ATI Radeon chip.
Just about any video card manufactured in the last year will run StepMania
flawlessly at 60 frames per second. I recommend any card with an nVidia
GeForce chip or an ATI Radeon chip.
* How can I improve performance with my existing video card
@@ -169,136 +240,391 @@ Just about any video card manufactured in the last year will run StepMania flawl
10. StepMania Packages - .smzip
************************************************************
The StepMania package format was created to make the distribution of songs and other add-ons very easy.  StepMania package files have the extension '.smzip' and can be installed by double-clicking the .smzip file.
The StepMania package format was created to make the distribution of songs and
other add-ons very easy.  StepMania package files have the extension '.smzip'
and can be installed by double-clicking the .smzip file.
A StepMania package is 'installed' by extracting all files in the package to the StepMania program directory. This allows songs, courses, themes, and visualizations to all be installed by the Package Manager.
A StepMania package is 'installed' by extracting all files in the package to the
StepMania program directory. This allows songs, courses, themes, and
visualizations to all be installed by the Package Manager.
The file format of an .smzip file is actually the PK-Zip standard.  This means you can rename any .smzip file to have the extension '.zip', and then open the file in any compression package (e.g. WinZip).
The file format of an .smzip file is actually the PK-Zip standard.  This means
you can rename any .smzip file to have the extension '.zip', and then open the
file in any compression package (e.g. WinZip).
The StepMania Package Manager (smpackage.exe) can also create song packages for you. Simply launch the Package Manager (Start Menu->Programs->StepMania->Package Manager), click the song you want to create a package for, click the Export button, and a .smzip package will be placed on your desktop.
The StepMania Package Manager (smpackage.exe) can also create song packages
for you. Simply launch the Package Manager
(Start Menu->Programs->StepMania->Package Manager), click the song you want to
create a package for, click the Export button, and a .smzip package will be
placed on your desktop.
************************************************************
11. Questions, Bugs, Suggestions, and Help
************************************************************
If you have a question or problem about StepMania, please try asking your question to the StepMania message board. A link is available from the StepMania web site http://www.stepmania.com.
If you have a question or problem about StepMania, please try asking your
question to the StepMania message board. A link is available from the StepMania
web site - http://www.stepmania.com.
If you have found a bug, please file a bug report into the SourceForge bug tracking system (http://sourceforge.net/tracker/?group_id=37892&atid=421366).  This will allow the developers to track and fix bugs much more efficiently.  
If you have found a bug, please file a bug report into the SourceForge bug
tracking system (http://sourceforge.net/tracker/?group_id=37892&atid=421366).  
This will allow the developers to track and fix bugs much more efficiently.  
* In a bug report, please specify your video card brand and model, and your OS version.
* PLEASE, PLEASE enter your e-mail address on the bug reports. In many cases, we need more information from the bug reporter.
* In a bug report, please specify your video card brand and model, and your OS
version.
* PLEASE, PLEASE enter your e-mail address on the bug reports. In many cases,
we need more information from the bug reporter.
Please use SourceForge's feature request system to enter new feature requests (http://sourceforge.net/tracker/?atid=421369&group_id=37892&func=browse). Also, please discuss feature ideas on the StepMania message board or the StepMania developers list ([email protected]).  
Please use SourceForge's feature request system to enter new feature requests
(http://sourceforge.net/tracker/?atid=421369&group_id=37892&func=browse). Also,
please discuss feature ideas on the StepMania message board or the StepMania
developers list ([email protected]).  
If you would like to help with development of StepMania, please send an email to the StepMania developers list ([email protected]) or to Chris ([email protected]).
If you would like to help with development of StepMania, please send an email
to the StepMania developers list ([email protected]) or to Chris
([email protected]).
************************************************************
12. The StepMania editor
************************************************************
The StepMania editor allows you to edit, record, synchronize, and play back note patterns. Current, it support saving only in the .SM format. If you save a song that was originally in DWI or BMS format, the old DWI and BMS files will be renamed to have ".old" appended to avoid conflicts when the song is next loaded. All of the commands are listed along the left side of the screen.
The StepMania editor allows you to edit, record, synchronize, and play back
note patterns. Current, it support saving only in the .SM format. If you save
a song that was originally in DWI or BMS format, the old DWI and BMS files will
be renamed to have ".old" appended to avoid conflicts when the song is next
loaded. All of the commands are listed along the left side of the screen.
************************************************************
13. The .SM file format
************************************************************
The .SM song file format was created to be one file format that supports all game types that StepMania can play (dance, pump, beat, guitar, etc). The .SM file syntax is identical to DWI except for some different tags and meanings. These are a list of all supported tags.
The .SM song file format was created to be one file format that supports all
game types that StepMania can play (dance, pump, beat, guitar, etc). The .SM
file syntax is identical to DWI except for some different tags and meanings.
These are a list of all supported tags.
All images can be in png, gif, jpg, or bmp format. All sounds can be in ogg, mp3, or wav format.
All images can be in png, gif, jpg, or bmp format. All sounds can be in ogg,
mp3, or wav format.
#TITLE:...; - The "main title" of the song.
#SUBTITLE:...; - This text will appear underneath the main title of the song on the Select Music screen. e.g. "-Dirty Mix-", "(remix)".
#SUBTITLE:...; - This text will appear underneath the main title of the song
on the Select Music screen. e.g. "-Dirty Mix-", "(remix)".
#ARTIST:...; - The artist of the song.
#CREDIT:...; - Give yourself some credit here for creating a wonderful song.
#BPM:...; - BPM of the music
#BANNER:...; - The file name of the banner image. e.g. "b4u-banner.png". This image must reside in the song folder.
#BACKGROUND:...; - The file name of the background image. e.g. "b4u-bg.png". This image must reside in the song folder.
#CDTITLE:...; - The file name of the spinning CD logo. e.g. "b4u-cdtitle.png". This image must reside in the song folder.
#MUSIC:...; - The file name of the music file. e.g. "b4u.mp3". This image must reside in the song folder.
#MUSICBYTES:...; - The size in bytes of the music file that this song was last synchronized with. A "Song may be out of synch" warning will be displayed if the value of this tag does not match the actual size of the music file.
#OFFSET:...; - The time in seconds at which beat 0 occurs in the music. This is specified as a floating point value. e.g. "2.34".
#SAMPLESTART:...; - The time in seconds to start the music sample that plays on the Select Music screen. This is specified as a floating point value. e.g. "32.34".
#SAMPLELENGTH:...; - The time in seconds let the sample music play after starting. This is specified as a floating point value. e.g. "32.34". Note that in the last 1 second of playing the music will fade out.
#FREEZE:...; - A value of the format "beat=sec". Indicates that at 'beat', the motion of the arrows should stop for "sec" seconds. Both of these values are specified as floating point values. Multiple freezes can be given by separating them with commas. e.g. "60=2.23,80=1.12".
#BPMS:...; - A value of the format "beat=bpm". Indicates that at 'beat', the speed of the arrows will change to "bpm". Both of these values are specified as floating point values. You must specifiy a BPM value for beat 0. Multiple freezes can be given by separating them with commas. e.g. "0=160,120=80".
#BANNER:...; - The file name of the banner image. e.g. "b4u-banner.png".
This image must reside in the song folder.
#BACKGROUND:...; - The file name of the background image. e.g. "b4u-bg.png".
This image must reside in the song folder.
#CDTITLE:...; - The file name of the spinning CD logo. e.g. "b4u-cdtitle.png".
This image must reside in the song folder.
#MOVIEBACKGROUND:...; - The file name of the a background movie. e.g. "b4u-movie.avi".
This movie must reside in the song folder.
#MUSIC:...; - The file name of the music file. e.g. "b4u.mp3". This image
must reside in the song folder.
#MUSICBYTES:...; - The size in bytes of the music file that this song was last
synchronized with. A "Song may be out of synch" warning will be displayed if
the value of this tag does not match the actual size of the music file.
#OFFSET:...; - The time in seconds at which beat 0 occurs in the music. This
is specified as a floating point value. e.g. "2.34".
#SAMPLESTART:...; - The time in seconds to start the music sample that plays
on the Select Music screen. This is specified as a floating point value. e.g.
"32.34".
#SAMPLELENGTH:...; - The time in seconds let the sample music play after
starting. This is specified as a floating point value. e.g. "32.34". Note
that in the last 1 second of playing the music will fade out.
#BPMS:...; - A value of the format "beat=bpm". Indicates that at 'beat', the
speed of the arrows will change to "bpm". Both of these values are specified
as floating point values. You must specifiy a BPM value for beat 0. Multiple
BPMs can be given by separating them with commas. e.g. "0=160,120=80".
#STOPS:...; - A value of the format "beat=sec". Indicates that at 'beat',
the motion of the arrows should stop for "sec" seconds. Both of these values
are specified as floating point values. Multiple stops can be given by
separating them with commas. e.g. "60=2.23,80=1.12".
#ANIMATIONS:...; - A value of the format "beat=anim name". Indicates that at 'beat',
the background animation should change to the animation names 'anim name'. 'beat'
is a floating point value and 'anim name' is a string. Different animation change
are separated by commas. e.g. "60=falling,80=flower".
Each pattern of steps for different modes have the same basic format:
#NOTES:(NotesType):(Description):(DifficultyClass):(DifficultyMeter):(RadarValues):(NoteData);
#NOTES:<NotesType>:<Description>:<DifficultyClass>:<DifficultyMeter>:<RadarValues>:<NoteData>;
NotesType: Must be one of the currently supported types in StepMania: "dance-single", "dance-double", "dance-couple", "dance-solo", "pump-single", "pump-double".
NotesType: Must be one of the currently supported types in StepMania:
"dance-single", "dance-double", "dance-couple", "dance-solo", "pump-single",
"pump-double".
Description: This will be displayed on the gameplay screen. This can be any text, but is most commonly "Basic", "Another", "Trick", "Standard", "SSR", "Maniac", "Heavy", or "Challenge".
Description: This will be displayed on the gameplay screen. This can be any
text, but is most commonly "Basic", "Another", "Trick", "Standard", "SSR",
"Maniac", "Heavy", or "Challenge".
DifficultyClass: This value must be "easy", "medium", or "hard". These values correspond the levels of difficulty on the Select Difficulty screen.
DifficultyClass: This value must be "easy", "medium", or "hard". These values
correspond the levels of difficulty on the Select Difficulty screen.
DifficultyMeter: The difficulty of these notes as a bar rating. The value must be an integer between 1 and 10.
DifficultyMeter: The difficulty of these notes as a bar rating. The value must
be an integer between 1 and 10.
RadarValues: The values that will be displayed on the Groove Radar as floats between 0.00 and 1.00. The 5 values must be separated by commas, and are specified in the order: "stream,voltage,air,freeze,chaos". For MAX300, these values are "0.95,0.98,0.22,0.12,0.13". These values will automatically be written when you save the song in the StepMania editor, but you may edit the .SM file afterward to tweak them.
RadarValues: The values that will be displayed on the Groove Radar as floats
between 0.00 and 1.00. The 5 values must be separated by commas, and are
specified in the order: "stream,voltage,air,freeze,chaos". For MAX300, these
values are "0.95,0.98,0.22,0.12,0.13". These values will automatically be
written when you save the song in the StepMania editor, but you may edit the
.SM file afterward to tweak them.
NoteData:
NoteData: This value requires a longer explanation. The format is pretty
similar to that used in KSF files.
, // measure 32
1000
Each note is represented by a character:
1 = a regular "tap note"
2 = beginning of a "hold note"
3 = end of a "hold note"
a-z,A-z = reserved for game types that have sounds associated with notes
Notes are grouped into rows. The number of notes in a row depends on the
NotesType field.
dance-single = 4 notes/row
dance-double = 8 notes/row
dance-couple = 8 notes/row
dance-solo = 6 notes/row
pump-single = 5 notes/row
pump-double = 10 notes/row
For example, a note row for a dance-single pattern may look like "1001" (press
Left and Right simultaneously. A note row for a dance-double pattern may look
like "10010000" (press Left and Right simultaneously on the left pad).
Note rows are grouped into measures. The number of note rows in a measure will
determine the time value of each note. For example, if there are 4 note rows
in a measure, each note will be treated as a quarter note. If there are 8 notes
rows in a measure, each note will be treated as a eighth note. If there are 12
notes rows in a measure, each note will be treated as a triplet note. Measures
are separated by a comma.
Example:
// measure 1
2010
0000
0100
0000
: // measure 2
0001
0100
0001
0000
3010
0000
1000
0000
, // measure 33
0010
0100
0010
0000
;
************************************************************
14. Background Animations
************************************************************
\BGAnimations\<anim folder>\<layer files>
The BGAnimations folder should contain several folders for individual background animations. Currently, these background animations cycle in order of their folder names, changing every 4 measures of the song.
In an animation folder, each sprite represents one layer. Multiple layers can be specified by having multiple sprites. Layers are drawn from back to front in order of their file name. Different "layer effects" are specified by adding tokens to the file name. Here are an explanation of the currently supported tokens:
usesongbg - Use the song's background file instead of this graphics file. Since this graphics file will not be used, you might want to make this graphic a 1x1 graphic to save space.
add - use additive blending instead of normal blending.
cyclecolor - cycle the color of the layer over the colors of the rainbow
cyclealpha - cycle the alpha channel of the layer over type
startonrandomframe - Start the animation on a random frame. This is mainly useful for Tile or Particle effects.
dontanimate - Stay on the first frame of this animation. This is only useful for layers with multiple frames.
(stretch effects) - These scretch the graphic across the extire screen.
scretchscrollleft,
stretchscrollright,
stretchscrollup,
stretchscrolldown,
- Scroll the layer in a direction
stretchwater,
stretchbubble,
stretchtwist,
stretchspin,
- Deform the background sprite with an effect. Only stretch spin is currently implemented.
(particle effects) - Use the graphic to make individual particles on the screen.
particlesspiralout,
particlesspiralin,
- Spiral particles away from/toward the center of the screen.
particlesfloatup,
particlesfloatdown,
particlesfloatleft,
particlesfloatright,
- Scroll the particles across the screen.
particlesbounce,
- Particles start traveling in random directions and bounce when they hit the edge of the screen.
(tile effects) - Tile the graphics across the screen, forming a grid of graphics.
tilestill,
tilescrollleft,
tilescrollright,
tilescrollup,
tilescrolldown,
- Scroll the tiles
tileflipx,
tileflipy,
- Flip the tiles along the X or Y axis.
tilepulse,
- Tiles zoom in and out.
************************************************************
14. Building StepMania from CVS source
15. The .CRS File Format
************************************************************
CVS is the repository that manages the StepMania source code. Our CVS server is graciously provided by SourceForge. You can get the absolute-latest bleeding edge updates to StepMania by taking the source from CVS. Below are instructions on how to configure your computer to download source code from CVS and complile the source into a working executable.
Place holder...
Header section...
#COURSE:...; - name of the course
#LIVES:<0..10>; - An integer between 0 and 10. This line is optional.
#REPEAT:<YES|NO>; - start over after last stage?
#SONG:<group folder>\<song folder>:<description>; -
group folder - The name of the folder that contains the song folder.
song folder - the name of the folder that contains files for the song
description - BASIC, TRICK, SSR, MANIAC, HEAVY, etc.
//The modifiers section could be a list of comma-separated tags, like:
//"1.5x,REVERSE,SUDDEN", etc. We'd have to come up with a standard set for
//features common to both SM and DWI... and new ones could be added for features
//only supported by SM perhaps (Space, Drunk, etc...).
//
//The number of songs in a course is just how many "#SONG:"... lines there are.
//
//So... and "ENDLESS" mode would be as simple as: #COURSE:Endless; #REPEATS:YES;
//#SONG:*:7..9;
//
//New features could be added to the end of the "#SONG" line in the future.
//...how does this all sound to you? That way courses could easily be used between
//versions and passed around. :)
//
************************************************************
15. Building StepMania from CVS source
************************************************************
CVS is the repository that manages the StepMania source code. Our CVS server is
graciously provided by SourceForge. You can get the absolute-latest bleeding
edge updates to StepMania by taking the source from CVS. Below are instructions
on how to configure your computer to download source code from CVS and complile
the source into a working executable.
* Step 1: Install and configure Visual C++
The StepMania source can currently be built with Microsoft Visual C++ 6.0 or Visual C++ .Net. Installing Visual C++ or Visual Studio with all the default options is sufficient.
The StepMania source can currently be built with Microsoft Visual C++ 6.0 or
Visual C++ .Net. Installing Visual C++ or Visual Studio with all the default
options is sufficient.
* Step 2: Install the Direct X 8.1 SDK
The DirectX 8.1 SDK is a free (but large) download from Microsoft (link here). Install it using all the default settings. The SDK installer will configure Visual C++ with the correct paths needed to find the DirectX 8.1 libraries and headers.
The DirectX 8.1 SDK is a free (but large) download from Microsoft (link here).
Install it using all the default settings. The SDK installer will configure
Visual C++ with the correct paths needed to find the DirectX 8.1 libraries and
headers.
* Step 3: Install WinCVS
A CVS client is required to "checkout" the course from the CVS server. Download version 1.2 of WinCVS here - http://www.cvsgui.org.
IMPORTANT: Now, open and close WinCVS once. This will cause WinCVS to create registry entries, which is required for the next step...
A CVS client is required to "checkout" the course from the CVS server. Download
version 1.2 of WinCVS here - http://www.cvsgui.org.
IMPORTANT: Now, open and close WinCVS once. This will cause WinCVS to create
registry entries, which is required for the next step...
* Step 4: Use SourceForge Setup to install SSH and configure WinCVS
A small utility called SourceForge Setup will greatly simplify the steps needed to configure SSH and WinCVS. Download SourceForge Setup here - link here. Use the following settings when prompted by SF Setup:
A small utility called SourceForge Setup will greatly simplify the steps needed
to configure SSH and WinCVS. Download SourceForge Setup here - link here. Use
the following settings when prompted by SF Setup:
- Unpack SSH directory: c:\ssh
- SSH install direcotory: c:\ssh
- Your home directory: c:\ssh
- Your SourceForge user name: -yourusername-
- Name of the project: stepmania
- The directory where you will be keeping checked out project sources: c:\stepmania
IMPORTANT: If you are using Windows 2000 or Windows XP SourceForge Setup will not correctly write changes to the c:\autoexec.bat file. Verify that the following lines are present after you run SF Setup:
- The directory where you will be keeping checked out project sources:
c:\stepmania
IMPORTANT: If you are using Windows 2000 or Windows XP SourceForge Setup will
not correctly write changes to the c:\autoexec.bat file. Verify that the
following lines are present after you run SF Setup:
rem SourceForge setup stuff
SET PATH=%PATH%;c:\ssh
SET HOME=c:\ssh
IMPORTANT: You must restart after running SF Setup so that the new environment variables take effect.
IMPORTANT: You must restart after running SF Setup so that the new environment
variables take effect.
* DONE! Enjoy staying on the bleeding edge of StepMania releases! 
************************************************************
15. Version History
16. Version History
************************************************************
------------------------Version 3.00 beta 4------------------
BUG FIX: Fixed crash entering Config Joy/Key (duh!)
BUG FIX: Smarter bannner/backgroung/cdtitle discovery
NEW FEATURE: Supports reading CDTitles from the .\CDTitles folder (compatible
with DWI). Song makers are not encouraged to use this feature and instead should
put the CDTitle graphic in the song folder. Having a separate CDTitles folder
breaks the principle that all files needed to play a song should reside in the
song folder.
BUG FIX: Fixed "D3DCreateTextureFromFile" error. This happend a lot on a Voodoo3
and Win98.
BUG FIX: Fixed "Divide by 0"/"Access Violoation" when loading a song - I think.
OPTIMIZATION: Faster loading at "Nth Stage" screen.
------------------------Version 3.00 beta 3------------------
BUG FIX: Fixed crash BemaniRuler's "Connected"
BUG FIX: #BPMCHANGE in DWI files now read fractional values (BemaniRuler's Naturally)
BUG FIX: Dizzy works correctly again
BUG FIX: Subtitle extraction now works for "Dub-I-Dub" and "SP-Trip Machine"
BUG FIX: No longer crashes on Titles starting with '('
BUG FIX: Earlier scrolling for songs that have early notes (BMR's A)
BUG FIX: Inserted blank time for songs that have note right at end of song (AM-3P)
OPTIMIZATION: Faster loading of gameplay screen
BUG FIX: Sample music no longer studders on Select Music screen
BUG FIX: "Shaky" artifacts no longer appear while holding a hold note
CHANGE: Re-added support for movie visualizations (by popular demand).
NEW FEATURE: Movie backgrounds. Either specify with the "#MOVIEBACKGROUND" tag,
or the first movie file in the song directory will be used. Works with
BemaniRuler's background movies. Background movie will not play will not play
if BackgroundMode is set to "OFF".
NEW FEATURE: Song-specific animations. Place all animations in a folder called
"BGAnimations" within the song folder. See "13. The .SM file format" and
"14. Background Animations" in README-FIRST.txt for details.
CHANGE: Appearance Options now available from Title Menu. Here you can choose
the announcer and note skin.
------------------------Version 3.00 beta 2------------------
BUG FIX: Fixed crash when loading MAX2 files from ddrei.com
CHANGE: "JudgeWindow" option name changed to "Difficulty"
CHANGE: Initial difficulty made easier
BUG FIX: Song loading now smarter about how it picks banners, backgrounds,
and CDTitles. See readme "6. How StepMania Loads Songs" for details.
BUG FIX: #BPMS in SM files now read fractional values
NEW FEATURE: Background brightness (Game Options)
BUG FIX: BemaniRuler songs (like Pulse) now loaded correctly
BUG FIX: Stationary arrows don't press unless note is a hit
BUG FIX: Size of combo text capped to a reasonable level
BUG FIX: Song background now stretched correctly when used in a background animation
OPTIMIZATION: Reduced lag while starting music sample (Select Music screen)
NEW FEATURE: Menu Timer - accessable from Game Options
BUG FIX: Changes saved in editor now show up immediately (instead of after restart)
------------------------Version 3.00 beta 1------------------
NEW FEATURE: Roulette
NEW FEATURE: AutoPlay (selectable from Game Options screen)
@@ -309,8 +635,10 @@ NEW FEATURE: "Judge Window" option to adjust difficulty of step judging
NEW FEATURE: Song data cache for faster loading.
NEW FEATURE: Groove Radar
NEW FEATURE: Dark Mode (selectable from Player Options screen)
NEW FEATURE (partially complete): Nonstop Challenge (Oni)
NEW FEATURE (partially complete): Pump It Up support
NEW FEATURE (partially complete): Background Animations (defaut animations go in BGAnimations dir)
NEW FEATURE (partially complete): Background Animations (defaut animations go in
BGAnimations dir)
------------------------Version 2.90-------------------------
CHANGE: Ogg Vorbis music support re-enabled
@@ -327,7 +655,8 @@ OPTIMIZATION: Major speedup to BitmapText loading
CHANGE: Menus changes to accomodate MAX-style menus
CHANGE: Now compiles in Visual C++.Net
OPTIMIZATION: Max texture size and texture color options are now supported.
BUG FIX: Scaled sprite alignment (no more transparent strip along the edge of "danger" static)
BUG FIX: Scaled sprite alignment (no more transparent strip along the edge of
"danger" static)
NEW FEATURE: Repeating input
NEW FEATURE: Select Group menu
NEW FEATURE: Edit / Record / Playback
@@ -338,9 +667,11 @@ BUG FIX: Statistics now save and load correctly
BUG FIX: Better framerate during gameplay
------------------------Version 1.64-------------------------
NEW FEATURE: Group banners on Select Music screen. Just put a banner in the group folder.
NEW FEATURE: Group banners on Select Music screen. Just put a banner in the group
folder.
BUG FIX: Hacked around a Savage texture loading bug.
CHANGE: Added "hold NEXT for options" after choosing a song. Most people don't know about this feature!
CHANGE: Added "hold NEXT for options" after choosing a song. Most people don't know
about this feature!
CHANGE: Faster song loading
CHANGE: more accurate synching at song rates other than 100%
CHANGE: Assist tick calibrated automatically by detecting sound card play latency
@@ -357,12 +688,14 @@ BUG FIX: Prefs, songs, and default mappings now load if StepMania.ini doesn't e
BUG FIX: Pad 2 can now be used to navigate the title screen
BUG FIX: Crash if change sort while a section item was selected
BUG FIX: BPM changes to 0 when section is selected
BUG FIX: Pixel/Texel alignment bug causing a strip of color along right and bottom edges moving between menus.
BUG FIX: Pixel/Texel alignment bug causing a strip of color along right and bottom
edges moving between menus.
BUG FIX: Graphical glitches on Results screen
BUG FIX: Hold Steps now look better when Scroll Speed is > 1
BUG FIX: Wrong Ghost Arrow graphic being used
BUG FIX: Boost/Scroll Speed interaction is now like MAX
BUG FIX: DWI's with newlines before semicolon are no longer corrupt when saving using Synchronize
BUG FIX: DWI's with newlines before semicolon are no longer corrupt when saving
using Synchronize
BUG FIX: #516498 - Installing Stepmania Deletes records
BUG FIX: #517003 - Joystick mappings not flushed
BUG FIX: Multiple NEXT presses not allowed on Caution screen
@@ -400,15 +733,18 @@ BUG FIX: #506597 - Empty Sort Crash
BUG FIX: #511543/#511186 - Visualizations not shown correctly
------------------------Version 1.59-------------------------
NEW FEATURE: More texture loading hints (DITHER, NO_MIP_MAPS) for increased quality and faster loading time.
NEW FEATURE: More texture loading hints (DITHER, NO_MIP_MAPS) for increased
quality and faster loading time.
BUG FIX: #506274 Crash changing song after sorting.
BUG FIX: #506343 TextureColor=32 Auto-Reset
CHANGE: SMLauncher integrated with the main StepMania executable. Now the pretty error screen will appear automatically.
CHANGE: SMLauncher integrated with the main StepMania executable. Now the
pretty error screen will appear automatically.
NEW FEATURE: Added Low-Medium-High detail prompt to installer.
NEW FEATURE: Song sort order is now rememebered.
OPTIMIZATION: Instantaneous Song Sort Order switch.
OPTIMIZATION: Instantaneous Song Group expand/collapse.
CHANGE: Song Sort groups that begin with a number now appear under the "NUM" group.
CHANGE: Song Sort groups that begin with a number now appear under the "NUM"
group.
BUG FIX: "Player's Best" is now sorted by num times played decending
BUG FIX: #506835 - PREV from Song Select Fade Glitch
BUG FIX: #506827 - Song Selected Graphic Errors
@@ -422,12 +758,14 @@ OPTIMIZATION: Improved animation of and optimized drawing of rolling score displ
OPTIMIZATION: Toned down motion blur effect in "Failed" for increased performance.
BUG FIX: Fixed matrix stack bug that caused some shadows not to draw
OPTIMIZATION: Major optimization of BitmapText. Now about 2x faster.
NEW FEATURE: F4-F8: Toggle Fullscreen, Change Resolution, Change Display Color, Change Texture Color, Toggle Statistics
NEW FEATURE: F4-F8: Toggle Fullscreen, Change Resolution, Change Display Color,
Change Texture Color, Toggle Statistics
NEW FEATURE: Remebers last selected Steps
NEW FEATURE: Stage number saved to .ini file.
BUG FIX: Default key buttons don't work if .ini file not present on startup
CHANGE: Hold Arrows are now drawn last to first, like in DDR MAX.
NEW FEATURE: Hold Arrows allow you to not hold the button for a second without NG'ing them.
NEW FEATURE: Hold Arrows allow you to not hold the button for a second without
NG'ing them.
CHANGE: Regular Arrows on the same line as a Hold Arrow now appear green.
NEW FEATURE: Hold Arrows now turn gray player doesn't hold the button.
BUG FIX: #510980 Danger is a static box, not text
@@ -435,30 +773,38 @@ BUG FIX: #510980 Danger is a static box, not text
------------------------Version 1.57-------------------------
NEW FEATURE: smzip package installer and manager
CHANGE: Installer now uninstalls previous version.
BUG FIX: Package Manager now converts all non-HTTP-friendly characters to '_' when exporting.
CHANGE: Much better texture loading algorithm. Texture quality and loading time of non-power of 2 texture improved greatly.
BUG FIX: Package Manager now converts all non-HTTP-friendly characters to '_' when
exporting.
CHANGE: Much better texture loading algorithm. Texture quality and loading time of
non-power of 2 texture improved greatly.
CHANGE: New 5th Mix theme graphics. Thanks thingmabobr!
BUG FIX: #507170 Speed Problem (Got rid of "pauses" caused by buffered writing to log)
BUG FIX: #507170 Speed Problem (Got rid of "pauses" caused by buffered writing to
log)
BUG FIX: #506309 Installer doesn't overwrite files
BUG FIX: #511187 old banners are shown diagonal
------------------------Version 1.56-------------------------
BUG FIX: 506314 Fixed "Hall of mirrors" on nVidia cards (actually, just a work around for a driver bug)
BUG FIX: 506314 Fixed "Hall of mirrors" on nVidia cards (actually, just a work
around for a driver bug)
CHANGE: Couple and Solo now appear in Select Style
CHANGE: New Title Menu options (but you can choose them yet :-)
BUG FIX: Fixed jibberish at the top of Arial Bold font by shifting all letters up one pixel
BUG FIX: Fixed jibberish at the top of Arial Bold font by shifting all letters
up one pixel
BUG FIX: 505896 Menu Problems [unreadable/illegible font?]
BUG FIX: Ugly textures with Voodoo3
BUG FIX: Ignore Joystick D-pad now works again.
BUG FIX: Installer-created icon "Open Songs Folder" now fixed for OSes that had problems.
BUG FIX: Installer-created icon "Open Songs Folder" now fixed for OSes that had
problems.
BUG FIX: BMS parse crash fixed.
BUG FIX: Player2 couldn't press up to select different steps
BUG FIX: Player2's side in StepsSelector no longer has multiple bouncing difficulty icons
BUG FIX: Player2's side in StepsSelector no longer has multiple bouncing difficulty
icons
BUG FIX: 507380 Multiple FAILED with Esc presses
BUG FIX: 507860 - Esc in No Fail Mode = lock up
CHANGE: Improved response time to user input when change sort in SelectMusic
BUG FIX: Announcer no longer makes dancing comments while FAILED is showing.
OPTIMIZATION: Added texture alpha hints - significantly improved texture quality for 16-bit textures.
OPTIMIZATION: Added texture alpha hints - significantly improved texture quality
for 16-bit textures.
------------------------Version 1.55-------------------------
BUG FIX: "4nd Stage" is now "4th Stage"
@@ -474,8 +820,10 @@ CHANGE: cleaned up debug messages
OPTIMIZATION: Improved texture loading time
CHANGE: Maximize button no longer toggles fullscreen.
CHANGE: MusicWheel response to user input is improved
OPTIMIZATION: Preview in SelectMusic now uses banner instead of background for faster loading
NEW FEATURE: Change resolution, display color depth, texture color depth, and toggle texture filtering
OPTIMIZATION: Preview in SelectMusic now uses banner instead of background for faster
loading
NEW FEATURE: Change resolution, display color depth, texture color depth, and toggle
texture filtering
NEW FEATURE: Check at startup time that all required theme elements are present
NEW FEATURE: installer
NEW FEATURE: motion blur "Failed" effect
@@ -485,11 +833,14 @@ CHANGE: All documentation is now in "Docs" folder
CHANGE: New "Danger" animation
------------------------Version 1.50-------------------------
Bug fix: No longer crashes on foreign chars in BMS files. Please report all songs that still cause a crash.
Change: Added sepatate background movie property to Song. Now status backgrounds will display in SelectMusic if the Song has a movie background.
Bug fix: No longer crashes on foreign chars in BMS files. Please report all songs that
still cause a crash.
Change: Added sepatate background movie property to Song. Now status backgrounds will
display in SelectMusic if the Song has a movie background.
Change: Asset directory structure has completely changed in preparation for theme support.
Optimization: BitmapText is now ~80% faster.
New Feature: 5th Mix style SelectMusic and auto-generated text banners. Loads 100x faster than the previous SelectSong screen.
New Feature: 5th Mix style SelectMusic and auto-generated text banners. Loads 100x faster
than the previous SelectSong screen.
Change: Error messages in Release builds no longer show source file line and number.
Bug Fix: Fade transition now fades all the way to black (doesn't leave a "hazy" screen).
Bug Fix: Multiple joysticks now work again.
@@ -497,16 +848,26 @@ Bug Fix: Multiple joysticks now work again.
-------------------------Version 0.97-------------------------
Bug fix: Songs with same title no longer change positions while scrolling.
Bug fix: Wrong group name for DWI files in the Songs folder.
Bug fix: Fixed a problem that caused the music to become out of sync if many sound effect are played. This was causing the song to become out of sync near the end. Note that this change makes the music much more accurate, and some BMS files may be out of sync if they appeared in sync before.
Bug fix: Dancing waits 2 seconds before starting music playback. This allows some slower systems to catch up.
Bug fix: Fixed a problem that caused the music to become out of sync if many sound
effect are played. This was causing the song to become out of sync near the end.
Note that this change makes the music much more accurate, and some BMS files may
be out of sync if they appeared in sync before.
Bug fix: Dancing waits 2 seconds before starting music playback. This allows some
slower systems to catch up.
Bug fix: Little now works correctly. It is accessible from the PlayerOptions menu.
Optimization: Lower priority for movie decoding, which is a major speed boost on slower computers.
Change: Freeze arrow scoring now matches DDR MAX. The start of a freeze arrow is judged as other steps are (perfect, great, good, etc).  Missing the start of a freeze will should break your combo, but NG'ing the freeze arrow will not.
New feature: Basic song statistics tracking. Times played, top score, top combo, and top grade are shown on SelectSong screen.
Optimization: Lower priority for movie decoding, which is a major speed boost on
slower computers.
Change: Freeze arrow scoring now matches DDR MAX. The start of a freeze arrow is judged
as other steps are (perfect, great, good, etc).  Missing the start of a freeze will
should break your combo, but NG'ing the freeze arrow will not.
New feature: Basic song statistics tracking. Times played, top score, top combo, and
top grade are shown on SelectSong screen.
New feature: Assist tick, accessible from the SongOptions menu.
New feature: Music Rate, accessible from the SongOptions menu. You can speed up or slow down the rate of music playback. Great for practicing hard step patterns.
New feature: Music Rate, accessible from the SongOptions menu. You can speed up or
slow down the rate of music playback. Great for practicing hard step patterns.
New feature: Freeze arrow scores are now shown on the Results screen.
Change: Arrow ghost now appear different depending on the combo length (roughly matches DDR MAX).
Change: Arrow ghost now appear different depending on the combo length (roughly matches
DDR MAX).
Change: Added some animation to the Results screen.
Change: Revamped input mapping to allow assignment and clearing of specific slots.
@@ -526,9 +887,12 @@ Bug fix: Freezes in Telephone Operator are now correct
Bug fix: Nonsense help messages fixed
Bug fix: D3D init failure now opens browser to correct troubleshooting page
Optimization: Drawing of freeze arrows is much more efficient
Optimization: In SelectSong, only one preview graphic is drawn. This saves fill rate and leaves room for group/sort/BPM text.
Change: DWI files now use the DWI directory structure. StepMania also automatically crop and rotate the song banner. BMS files still reside in the Songs folder.
Change: Now hold Next to get to PlayerOptions and SongOptions menus (Previously, you would hold Next to bypass these menus).
Optimization: In SelectSong, only one preview graphic is drawn. This saves fill rate
and leaves room for group/sort/BPM text.
Change: DWI files now use the DWI directory structure. StepMania also automatically
crop and rotate the song banner. BMS files still reside in the Songs folder.
Change: Now hold Next to get to PlayerOptions and SongOptions menus (Previously, you
would hold Next to bypass these menus).
New feautre: FPS counter. Can toggle from GameOptions.
New feature: Disable joystick d-pad (for DirectPad Pro and NTPad).
New Feature: Song background movies
+26 -4
View File
@@ -11,6 +11,7 @@
*/
#include "AnnouncerManager.h"
#include "PrefsManager.h"
#include "RageLog.h"
@@ -26,11 +27,10 @@ AnnouncerManager::AnnouncerManager()
{
CStringArray arrayAnnouncerNames;
GetAnnouncerNames( arrayAnnouncerNames );
for( int i=0; i<arrayAnnouncerNames.GetSize(); i++ )
AssertAnnouncerIsComplete( arrayAnnouncerNames[i] );
// for( int i=0; i<arrayAnnouncerNames.GetSize(); i++ )
// AssertAnnouncerIsComplete( arrayAnnouncerNames[i] );
//SwitchAnnouncer( DEFAULT_ANNOUNCER_NAME );
SwitchAnnouncer( arrayAnnouncerNames[0] );
SwitchAnnouncer( PREFSMAN->m_sAnnouncer );
}
void AnnouncerManager::GetAnnouncerNames( CStringArray& AddTo )
@@ -47,6 +47,24 @@ void AnnouncerManager::GetAnnouncerNames( CStringArray& AddTo )
void AnnouncerManager::SwitchAnnouncer( CString sAnnouncerName )
{
if( sAnnouncerName == "" )
{
m_sCurAnnouncerName = "";
return;
}
CStringArray asAnnouncerNames;
GetAnnouncerNames( asAnnouncerNames );
for( int i=0; i<asAnnouncerNames.GetSize(); i++ )
if( asAnnouncerNames[i] == sAnnouncerName )
goto announcer_exists;
// if we get here, the announcer doesn't exist
sAnnouncerName = asAnnouncerNames[0];
announcer_exists:
m_sCurAnnouncerName = sAnnouncerName;
CString sAnnouncerDir = GetAnnouncerDirFromName( m_sCurAnnouncerName );
if( !DoesFileExist( sAnnouncerDir ) )
@@ -75,6 +93,9 @@ CString AnnouncerManager::GetPathTo( AnnouncerElement ae )
CString AnnouncerManager::GetPathTo( AnnouncerElement ae, CString sAnnouncerName )
{
if( sAnnouncerName == "" )
return ""; // hopefully there are no sound files here
CString sAssetDir;
switch( ae )
@@ -107,6 +128,7 @@ CString AnnouncerManager::GetPathTo( AnnouncerElement ae, CString sAnnouncerName
case ANNOUNCER_EVALUATION_FINAL_C: sAssetDir = "evaluation final c"; break;
case ANNOUNCER_EVALUATION_FINAL_D: sAssetDir = "evaluation final d"; break;
case ANNOUNCER_GAME_OVER: sAssetDir = "game over"; break;
case ANNOUNCER_MENU_HURRY_UP: sAssetDir = "menu hurry up"; break;
case ANNOUNCER_MUSIC_SCROLL: sAssetDir = "music scroll"; break;
case ANNOUNCER_EVALUATION_A: sAssetDir = "evaluation a"; break;
case ANNOUNCER_EVALUATION_AA: sAssetDir = "evaluation aa"; break;
+2 -1
View File
@@ -43,6 +43,7 @@ enum AnnouncerElement {
ANNOUNCER_EVALUATION_FINAL_C,
ANNOUNCER_EVALUATION_FINAL_D,
ANNOUNCER_GAME_OVER,
ANNOUNCER_MENU_HURRY_UP,
ANNOUNCER_MUSIC_SCROLL,
ANNOUNCER_EVALUATION_A,
ANNOUNCER_EVALUATION_AA,
@@ -100,7 +101,7 @@ protected:
CString GetAnnouncerDirFromName( CString sAnnouncerName );
CString GetElementDir( AnnouncerElement te );
CString m_sCurAnnouncerName;
CString m_sCurAnnouncerName; // "" means no announcer
};
+226 -97
View File
@@ -17,15 +17,41 @@
#include "RageBitmapTexture.h"
const CString MOVIE_VIS_DIR = "Visualizations\\";
const CString BG_ANIMS_DIR = "BGAnimations\\";
const CString VISUALIZATIONS_DIR = "Visualizations\\";
int CompareAnimSegs(const void *arg1, const void *arg2)
{
// arg1 and arg2 are of type Step**
AnimSeg* seg1 = (AnimSeg*)arg1;
AnimSeg* seg2 = (AnimSeg*)arg2;
float score1 = seg1->m_fStartBeat;
float score2 = seg2->m_fStartBeat;
if( score1 == score2 )
return 0;
else if( score1 < score2 )
return -1;
else
return 1;
}
void SortAnimSegArray( CArray<AnimSeg,AnimSeg&> &arrayAnimSegs )
{
qsort( arrayAnimSegs.GetData(), arrayAnimSegs.GetSize(), sizeof(AnimSeg), CompareAnimSegs );
}
Background::Background()
{
m_fSongBeat = 0;
m_bFreeze = false;
m_bShowDanger = false;
m_bInDanger = false;
m_BackgroundMode = MODE_STATIC_BG;
m_sprDanger.SetZoom( 2 );
m_sprDanger.SetEffectWagging();
@@ -33,157 +59,260 @@ Background::Background()
m_sprDanger.SetXY( CENTER_X, CENTER_Y );
m_sprDangerBackground.Load( THEME->GetPathTo(GRAPHIC_GAMEPLAY_DANGER_BACKGROUND) );
m_sprDangerBackground.StretchTo( CRect((int)SCREEN_LEFT, (int)SCREEN_TOP, (int)SCREEN_RIGHT, (int)SCREEN_BOTTOM) );
m_sprDangerBackground.StretchTo( CRect(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) );
m_pCurBackgroundAnimation = NULL;
m_quadBGBrightness.StretchTo( CRect(SCREEN_LEFT, SCREEN_TOP, SCREEN_RIGHT, SCREEN_BOTTOM) );
m_quadBGBrightness.SetDiffuseColor( D3DXCOLOR(0,0,0,1-0.5f) );
}
Background::~Background()
{
for( int i=0; i<m_BackgroundAnimations.GetSize(); i++ )
delete m_BackgroundAnimations[i];
}
bool Background::LoadFromSong( Song* pSong, bool bDisableVisualizations )
{
//
// Load background animations
//
CStringArray asBGAnimNames;
m_fMusicSeconds = 0;
m_bStartedBGMovie = false;
// We're going to try to classify songs as trance, pop, or techno based on some data about the song
if( pSong->m_BPMSegments.GetSize() + pSong->m_FreezeSegments.GetSize() >= 3 )
GetDirListing( BG_ANIMS_DIR+"techno*.*", asBGAnimNames, true );
else if( pSong->m_BPMSegments[0].m_fBPM > 160 )
GetDirListing( BG_ANIMS_DIR+"trance*.*", asBGAnimNames, true );
m_pSong = pSong;
//
// figure out what BackgroundMode to use
//
if( PREFSMAN->m_BackgroundMode == PrefsManager::BGMODE_OFF )
m_BackgroundMode = MODE_STATIC_BG;
else if( pSong->HasMovieBackground() )
m_BackgroundMode = MODE_MOVIE_BG;
else if( PREFSMAN->m_BackgroundMode == PrefsManager::BGMODE_MOVIEVIS )
m_BackgroundMode = MODE_MOVIE_VIS;
else
GetDirListing( BG_ANIMS_DIR+"pop*.*", asBGAnimNames, true );
// pick 4 random animations from this array
for( int i=0; i<asBGAnimNames.GetSize(); i++ )
m_BackgroundAnimations.Add( new BackgroundAnimation(BG_ANIMS_DIR + asBGAnimNames[i], pSong) );
m_BackgroundMode = MODE_ANIMATIONS;
//
// load song background
// force reload, dither, and stretch (stretch is needed by background animations for scrolling effects)
//
// CString sBackgroundMoviePath;
// if( pSong->HasBackgroundMovie() )
// {
// m_sprSongBackground.Load( pSong->GetBackgroundMoviePath() );
// m_sprSongBackground.SetZoomY( -1 ); // flip
// }
// else
if( pSong->HasBackground() )
{
m_sprSongBackground.Load( pSong->GetBackgroundPath(), false, 2, 0, true );
}
else
{
m_sprSongBackground.Load( THEME->GetPathTo(GRAPHIC_FALLBACK_BACKGROUND), false, 2, 0, true );
}
m_sprSongBackground.StretchTo( CRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ) );
m_sprSongBackground.SetDiffuseColor( D3DXCOLOR(0,0,0,1) );
m_sprSongBackground.Load( pSong->HasBackground() ? pSong->GetBackgroundPath() : THEME->GetPathTo(GRAPHIC_FALLBACK_BACKGROUND), true, 2, 0, true, m_BackgroundMode==MODE_ANIMATIONS );
m_sprSongBackground.StretchTo( CRect(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) );
if( PREFSMAN->m_visMode == VIS_MODE_MOVIE && !bDisableVisualizations )
switch( m_BackgroundMode )
{
// load a random visualization
CStringArray sVisualizationNames;
GetDirListing( MOVIE_VIS_DIR + "*.avi", sVisualizationNames );
GetDirListing( MOVIE_VIS_DIR + "*.mpg", sVisualizationNames );
GetDirListing( MOVIE_VIS_DIR + "*.mpeg", sVisualizationNames );
if( sVisualizationNames.GetSize() > 0 ) // there is at least one visualization
case MODE_STATIC_BG:
// do nothing
break;
case MODE_MOVIE_BG:
m_sprMovieBackground.Load( pSong->GetMovieBackgroundPath() );
m_sprMovieBackground.StretchTo( CRect(SCREEN_LEFT+10,SCREEN_TOP+16,SCREEN_RIGHT-10,SCREEN_BOTTOM-16) );
m_sprMovieBackground.SetZoomY( m_sprMovieBackground.GetZoomY()*-1 );
m_sprMovieBackground.StopAnimating( );
break;
case MODE_MOVIE_VIS:
{
int iIndexRandom = rand() % sVisualizationNames.GetSize();
m_sprVisualizationOverlay.Load( MOVIE_VIS_DIR + sVisualizationNames[iIndexRandom] );
m_sprVisualizationOverlay.StretchTo( CRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ) );
m_sprVisualizationOverlay.SetZoomY( m_sprVisualizationOverlay.GetZoomY()*-1 );
m_sprVisualizationOverlay.SetBlendModeAdd();
m_sprVisualizationOverlay.SetDiffuseColor( D3DXCOLOR(0,0,0,0) );
this->AddActor( &m_sprVisualizationOverlay );
CStringArray arrayPossibleMovies;
GetDirListing( VISUALIZATIONS_DIR + CString("*.avi"), arrayPossibleMovies );
GetDirListing( VISUALIZATIONS_DIR + CString("*.mpg"), arrayPossibleMovies );
GetDirListing( VISUALIZATIONS_DIR + CString("*.mpeg"), arrayPossibleMovies );
if( arrayPossibleMovies.GetSize() > 0 )
{
int index = rand() % arrayPossibleMovies.GetSize();
m_sprMovieVis.Load( VISUALIZATIONS_DIR + arrayPossibleMovies[index] );
m_sprMovieVis.StretchTo( CRect(SCREEN_LEFT,SCREEN_TOP,SCREEN_RIGHT,SCREEN_BOTTOM) );
m_sprMovieVis.SetZoomY( m_sprMovieVis.GetZoomY()*-1 );
m_sprMovieVis.SetBlendModeAdd();
}
}
break;
case MODE_ANIMATIONS:
{
//
// Load background animations
//
CStringArray asBGAnimNames;
// First look in the song folder for animations
GetDirListing( pSong->m_sSongDir+"BGAnimations\\*.*", asBGAnimNames, true );
if( asBGAnimNames.GetSize() > 0 )
{
for( int i=0; i<asBGAnimNames.GetSize(); i++ )
m_BackgroundAnimations.Add( new BackgroundAnimation(pSong->m_sSongDir+"BGAnimations\\"+asBGAnimNames[i], pSong) );
}
else
{
// We're going to try to classify songs as trance, pop, or techno based on some data about the song
if( pSong->m_BPMSegments.GetSize() + pSong->m_StopSegments.GetSize() >= 3 )
GetDirListing( BG_ANIMS_DIR+"techno*.*", asBGAnimNames, true );
else if( pSong->m_BPMSegments[0].m_fBPM > 160 )
GetDirListing( BG_ANIMS_DIR+"trance*.*", asBGAnimNames, true );
else
GetDirListing( BG_ANIMS_DIR+"pop*.*", asBGAnimNames, true );
// load different animations
for( int i=0; i<asBGAnimNames.GetSize(); i++ )
m_BackgroundAnimations.Add( new BackgroundAnimation(BG_ANIMS_DIR + asBGAnimNames[i], pSong) );
}
if( m_BackgroundAnimations.GetSize() == 0 )
break;
// Load a background animation plan into m_aAnimSegs
if( pSong->m_AnimationSegments.GetSize() > 0 )
{
// the song has a plan. Use it.
for( int i=0; i<pSong->m_AnimationSegments.GetSize(); i++ )
{
const AnimationSegment& aniseg = pSong->m_AnimationSegments[i];
int iIndex = -1;
for( int j=0; j<asBGAnimNames.GetSize(); j++ )
{
if( asBGAnimNames[j] == aniseg.m_sAnimationName )
{
iIndex = j;
break;
}
}
if( iIndex == -1 ) // this animation doesn't exist in the song dir
iIndex = rand() % m_BackgroundAnimations.GetSize(); // use a random one instead
m_aAnimSegs.Add( AnimSeg(aniseg.m_fStartBeat, iIndex) );
}
SortAnimSegArray( m_aAnimSegs ); // this should already be sorted
}
else
{
// Generate a plan.
for( int i=0; i<pSong->m_fLastBeat; i+=16 )
m_aAnimSegs.Add( AnimSeg((float)i,rand()%m_BackgroundAnimations.GetSize()) ); // change BG every 4 bars
for( i=0; i<pSong->m_BPMSegments.GetSize(); i++ )
{
const BPMSegment& bpmseg = pSong->m_BPMSegments[i];
m_aAnimSegs.Add( AnimSeg(bpmseg.m_fStartBeat,int(bpmseg.m_fBPM)%m_BackgroundAnimations.GetSize()) ); // change BG every BPM change
}
SortAnimSegArray( m_aAnimSegs );
}
}
break;
default:
ASSERT(0);
}
return true;
}
void Background::Update( float fDeltaTime )
{
ActorFrame::Update( fDeltaTime );
if( m_fSongBeat < 8 )
m_pCurBackgroundAnimation = NULL;
else
{
if( m_BackgroundAnimations.GetSize() > 0 )
{
int iIndexToSwitchTo = int(m_fSongBeat/BEATS_PER_MEASURE/4) % m_BackgroundAnimations.GetSize();
m_pCurBackgroundAnimation = m_BackgroundAnimations[ iIndexToSwitchTo ];
}
}
if( DangerVisible() )
{
m_sprDangerBackground.Update( fDeltaTime );
m_sprDanger.Update( fDeltaTime );
}
else
{
switch( PREFSMAN->m_visMode )
{
if( m_bFreeze )
return;
m_sprSongBackground.Update( fDeltaTime );
switch( m_BackgroundMode )
{
case VIS_MODE_ANIMATION:
if( m_pCurBackgroundAnimation && !m_bFreeze )
m_pCurBackgroundAnimation->Update( fDeltaTime, m_fSongBeat );
else
m_sprSongBackground.Update( fDeltaTime );
case MODE_STATIC_BG:
// do nothing
break;
case VIS_MODE_MOVIE:
m_sprVisualizationOverlay.Update( fDeltaTime );
// fall through and draw background
case VIS_MODE_NONE:
m_sprSongBackground.Update( fDeltaTime );
case MODE_MOVIE_BG:
m_sprMovieBackground.Update( fDeltaTime );
break;
case MODE_MOVIE_VIS:
m_sprMovieVis.Update( fDeltaTime );
break;
case MODE_ANIMATIONS:
if( GetCurBGA() )
GetCurBGA()->Update( fDeltaTime, m_fSongBeat );
break;
default:
ASSERT(0);
}
m_quadBGBrightness.Update( fDeltaTime );
}
m_sprVisualizationOverlay.Update( fDeltaTime );
m_sprSongBackground.Update( fDeltaTime );
m_sprDanger.Update( fDeltaTime );
m_sprDangerBackground.Update( fDeltaTime );
}
void Background::SetSongBeat( const float fSongBeat, const bool bFreeze, const float fMusicSeconds )
{
m_fSongBeat = fSongBeat;
m_bFreeze = bFreeze;
m_fMusicSeconds = fMusicSeconds;
if( m_BackgroundMode == MODE_MOVIE_BG && !m_bStartedBGMovie && m_fMusicSeconds > 0 )
m_sprMovieBackground.StartAnimating();
}
void Background::DrawPrimitives()
{
ActorFrame::DrawPrimitives();
if( DangerVisible() )
{
m_sprDangerBackground.Draw();
m_sprDanger.Draw();
}
else
{
switch( PREFSMAN->m_visMode )
{
switch( m_BackgroundMode )
{
case VIS_MODE_ANIMATION:
if( m_pCurBackgroundAnimation )
m_pCurBackgroundAnimation->Draw();
case MODE_STATIC_BG:
m_sprSongBackground.Draw();
break;
case MODE_MOVIE_BG:
::Sleep(4); // let the movie decode a frame
m_sprMovieBackground.Draw();
break;
case MODE_MOVIE_VIS:
m_sprSongBackground.Draw();
::Sleep(4); // let the movie decode a frame
m_sprMovieVis.Draw();
break;
case MODE_ANIMATIONS:
if( GetCurBGA() )
GetCurBGA()->Draw();
else
m_sprSongBackground.Draw();
break;
case VIS_MODE_MOVIE:
m_sprSongBackground.Draw();
m_sprVisualizationOverlay.Draw();
break;
case VIS_MODE_NONE:
m_sprSongBackground.Draw();
break;
default:
ASSERT(0);
}
m_quadBGBrightness.Draw();
}
}
bool Background::DangerVisible()
{
return m_bShowDanger && (TIMER->GetTimeSinceStart() - (int)TIMER->GetTimeSinceStart()) > 0.5f;
return m_bInDanger && (TIMER->GetTimeSinceStart() - (int)TIMER->GetTimeSinceStart()) > 0.5f;
}
void Background::FadeIn()
{
m_quadBGBrightness.BeginTweening( 0.5f );
m_quadBGBrightness.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,1-PREFSMAN->m_fBGBrightness) );
}
void Background::FadeOut()
{
m_quadBGBrightness.BeginTweening( 0.5f );
m_quadBGBrightness.SetTweenDiffuseColor( D3DXCOLOR(0,0,0,1-0.5f) );
}
+51 -16
View File
@@ -13,53 +13,88 @@
#include "Sprite.h"
#include "Quad.h"
#include "ActorFrame.h"
#include "Song.h"
#include "BackgroundAnimation.h"
struct AnimSeg
{
AnimSeg() {};
AnimSeg( float b, int i ) { m_fStartBeat = b; m_iAnimationIndex = i; };
float m_fStartBeat;
int m_iAnimationIndex;
};
class Background : public ActorFrame
{
public:
Background();
~Background();
virtual bool LoadFromSong( Song *pSong, bool bDisableVisualizations = false );
virtual void Update( float fDeltaTime );
virtual void DrawPrimitives();
void SetSongBeat( const float fSongBeat, const bool bFreeze ) { m_fSongBeat = fSongBeat; m_bFreeze = bFreeze; };
void SetSongBeat( const float fSongBeat, const bool bFreeze, const float fMusicSeconds );
virtual void SetDiffuseColor( D3DXCOLOR c )
{
m_sprSongBackground.SetDiffuseColor( c );
m_sprVisualizationOverlay.SetDiffuseColor( c );
m_sprSongBackground.SetDiffuseColor( c );
m_sprDanger.SetDiffuseColor( c );
m_sprDangerBackground.SetDiffuseColor( c );
};
void FadeIn();
void FadeOut();
virtual void TurnDangerOn() { m_bShowDanger = true; };
virtual void TurnDangerOff() { m_bShowDanger = false; };
virtual void TurnDangerOn() { m_bInDanger = true; };
virtual void TurnDangerOff() { m_bInDanger = false; };
virtual bool IsDangerOn() { return m_bShowDanger; };
virtual bool IsInDanger() { return m_bInDanger; };
protected:
bool DangerVisible();
CArray<BackgroundAnimation*,BackgroundAnimation*> m_BackgroundAnimations;
BackgroundAnimation* m_pCurBackgroundAnimation;
Song* m_pSong;
Sprite m_sprVisualizationOverlay;
enum BackgroundMode { MODE_STATIC_BG, MODE_MOVIE_BG, MODE_ANIMATIONS, MODE_MOVIE_VIS };
BackgroundMode m_BackgroundMode;
Sprite m_sprSongBackground;
Sprite m_sprDanger;
Sprite m_sprDangerBackground;
bool m_bShowDanger;
// for movie BG
Sprite m_sprMovieBackground;
// for animations
CArray<BackgroundAnimation*,BackgroundAnimation*> m_BackgroundAnimations;
CArray<AnimSeg,AnimSeg&> m_aAnimSegs;
BackgroundAnimation* GetCurBGA()
{
if( m_aAnimSegs.GetSize() == 0 )
return NULL;
if( m_fSongBeat < m_pSong->m_fFirstBeat || m_fSongBeat > m_pSong->m_fLastBeat )
return NULL;
for( int i=0; i<m_aAnimSegs.GetSize()-1; i++ )
if( m_aAnimSegs[i+1].m_fStartBeat > m_fSongBeat )
break;
int iIndex = m_aAnimSegs[i].m_iAnimationIndex;
return m_BackgroundAnimations[iIndex];
};
// for movie vis
Sprite m_sprMovieVis;
Quad m_quadBGBrightness;
bool m_bInDanger;
float m_fSongBeat;
bool m_bFreeze;
float m_fMusicSeconds;
bool m_bStartedBGMovie;
};
+1 -1
View File
@@ -52,7 +52,7 @@ bool Banner::LoadFromSong( Song* pSong ) // NULL means no song
if( pSong == NULL ) Banner::Load( THEME->GetPathTo(GRAPHIC_FALLBACK_BANNER) );
else if( pSong->HasBanner() ) Banner::Load( pSong->GetBannerPath() );
else if( pSong->HasBackground() ) Banner::Load( pSong->GetBackgroundPath() );
// else if( pSong->HasBackground() ) Banner::Load( pSong->GetBackgroundPath() );
else Banner::Load( THEME->GetPathTo(GRAPHIC_FALLBACK_BANNER) );
return true;
+1 -1
View File
@@ -124,7 +124,7 @@ typedef struct {
//
#include "baseclasses/reftime.h" // Helper class for REFERENCE_TIME management
#include "baseclasses/wxdebug.h" // Debug support for logging and ASSERTs
#include <amvideo.h> // ActiveMovie video interfaces and definitions
#include "baseclasses/amvideo.h" // ActiveMovie video interfaces and definitions
//include amaudio.h explicitly if you need it. it requires the DX SDK.
//#include <amaudio.h> // ActiveMovie audio interfaces and definitions
+21 -1
View File
@@ -11,6 +11,8 @@
#include "Combo.h"
#include "ThemeManager.h"
#include "ScreenManager.h"
#include "ScreenGameplay.h"
Combo::Combo()
@@ -46,6 +48,21 @@ void Combo::ContinueCombo()
if( m_iCurCombo > m_iMaxCombo )
m_iMaxCombo = m_iCurCombo;
switch( m_iMaxCombo )
{
case 100: SCREENMAN->SendMessageToTopScreen( SM_100Combo, 0 ); break;
case 200: SCREENMAN->SendMessageToTopScreen( SM_200Combo, 0 ); break;
case 300: SCREENMAN->SendMessageToTopScreen( SM_300Combo, 0 ); break;
case 400: SCREENMAN->SendMessageToTopScreen( SM_400Combo, 0 ); break;
case 500: SCREENMAN->SendMessageToTopScreen( SM_500Combo, 0 ); break;
case 600: SCREENMAN->SendMessageToTopScreen( SM_600Combo, 0 ); break;
case 700: SCREENMAN->SendMessageToTopScreen( SM_700Combo, 0 ); break;
case 800: SCREENMAN->SendMessageToTopScreen( SM_800Combo, 0 ); break;
case 900: SCREENMAN->SendMessageToTopScreen( SM_900Combo, 0 ); break;
case 1000: SCREENMAN->SendMessageToTopScreen( SM_1000Combo, 0 ); break;
}
if( m_iCurCombo <= 4 )
{
m_textComboNumber.SetDiffuseColor( D3DXCOLOR(1,1,1,0) ); // invisible
@@ -57,7 +74,7 @@ void Combo::ContinueCombo()
m_sprCombo.SetDiffuseColor( D3DXCOLOR(1,1,1,1) ); // visible
m_textComboNumber.SetText( ssprintf("%d", m_iCurCombo) );
float fNewZoom = 0.5f + m_iCurCombo/800.0f;
float fNewZoom = min( 0.5f + m_iCurCombo/800.0f, 1.1f );
m_textComboNumber.SetZoom( fNewZoom );
//this->SetZoom( 1.2f );
@@ -68,6 +85,9 @@ void Combo::ContinueCombo()
void Combo::EndCombo()
{
if( m_iCurCombo > 50 )
SCREENMAN->SendMessageToTopScreen( SM_ComboStopped, 0 );
m_iCurCombo = 0;
m_textComboNumber.SetDiffuseColor( D3DXCOLOR(1,1,1,0) ); // invisible
+3 -3
View File
@@ -66,10 +66,10 @@ void CourseContentsFrame::SetFromCourse( Course* pCourse )
m_Meters[i].SetFromNotes( NULL );
Song* pSong = pCourse->m_apSongs[i];
for( int j=0; j<pSong->m_arrayNotes.GetSize(); j++ )
for( int j=0; j<pSong->m_apNotes.GetSize(); j++ )
{
Notes* pNotes = pSong->m_arrayNotes[j];
if( pSong->m_arrayNotes[j]->m_DifficultyClass == pCourse->m_aDifficultyClasses[i] )
Notes* pNotes = pSong->m_apNotes[j];
if( pSong->m_apNotes[j]->m_DifficultyClass == pCourse->m_aDifficultyClasses[i] )
{
m_Meters[i].SetFromNotes( pNotes );
break;
+1 -1
View File
@@ -55,7 +55,7 @@ void CroppedSprite::CropToSize( float fWidth, float fHeight )
float fFinalZoom = this->GetZoom();
// find which dimension is larger
bool bXDimNeedsToBeCropped = GetZoomedWidth() > m_fCropWidth;
bool bXDimNeedsToBeCropped = GetZoomedWidth() > m_fCropWidth+0.01;
if( bXDimNeedsToBeCropped ) // crop X
{
+2 -2
View File
@@ -48,7 +48,7 @@ enum
MAX_NOTE_TRACKS // leave this at the end
};
const int MAX_BEATS = 300 * 2; // 300 bpm * 2 mins
const int MAX_BEATS = 1500; // BMR's Pulse has about 1300
const int BEATS_PER_MEASURE = 4;
const int MAX_MEASURES = MAX_BEATS / BEATS_PER_MEASURE;
@@ -56,7 +56,7 @@ const int ELEMENTS_PER_BEAT = 12; // It is important that this number is evenly
const int ELEMENTS_PER_MEASURE = ELEMENTS_PER_BEAT * BEATS_PER_MEASURE;
const int MAX_TAP_NOTE_ROWS = MAX_BEATS*ELEMENTS_PER_BEAT;
const int MAX_HOLD_NOTE_ELEMENTS = 200;
const int MAX_HOLD_NOTES = 400; // BMR's Connected has about 300
enum NoteType
{
+12 -5
View File
@@ -11,7 +11,7 @@
*/
#include "GameManager.h"
#include "PrefsManager.h"
GameManager* GAMEMAN = NULL; // global and accessable from anywhere in our program
@@ -557,8 +557,15 @@ GameManager::GameManager()
CStringArray asSkinNames;
GetSkinNames( asSkinNames );
for( int p=0; p<NUM_PLAYERS; ++p )
m_sCurrentSkin[p] = asSkinNames[0];
m_sCurrentSkin = PREFSMAN->m_sNoteSkin;
for( int i=0; i<asSkinNames.GetSize(); i++ )
{
if( m_sCurrentSkin == asSkinNames[i] )
goto skin_exists;
}
m_sCurrentSkin = asSkinNames[0];
skin_exists:
m_sMasterPlayerNumber = PLAYER_1;
}
@@ -600,12 +607,12 @@ CString GameManager::GetPathToGraphic( const PlayerNumber p, const int col, cons
StyleInput si( p, col );
GameInput gi = GetCurrentStyleDef()->StyleInputToGameInput( si );
InstrumentButton b = gi.button;
return GetCurrentGameDef()->GetPathToGraphic( m_sCurrentSkin[p], b, gbg );
return GetCurrentGameDef()->GetPathToGraphic( m_sCurrentSkin, b, gbg );
}
void GameManager::GetTweenColors( const PlayerNumber p, const int col, CArray<D3DXCOLOR,D3DXCOLOR> &aTweenColorsAddTo )
{
StyleInput StyleI( p, col );
GameInput GameI = GetCurrentStyleDef()->StyleInputToGameInput( StyleI );
GetCurrentGameDef()->GetTweenColors( m_sCurrentSkin[p], GameI.button, aTweenColorsAddTo );
GetCurrentGameDef()->GetTweenColors( m_sCurrentSkin, GameI.button, aTweenColorsAddTo );
}
+1 -1
View File
@@ -25,7 +25,7 @@ public:
Game m_CurGame;
Style m_CurStyle;
NotesType m_CurNotesType; // only used in Edit
CString m_sCurrentSkin[NUM_PLAYERS];
CString m_sCurrentSkin;
PlayerNumber m_sMasterPlayerNumber;
GameDef* GetCurrentGameDef();
+4 -4
View File
@@ -35,10 +35,10 @@ void GhostArrow::Step( TapNoteScore score )
{
switch( score )
{
case TNS_PERFECT: SetDiffuseColor( D3DXCOLOR(1.0f,1.0f,0.3f,0.6f) ); break; // yellow
case TNS_GREAT: SetDiffuseColor( D3DXCOLOR(0.0f,1.0f,0.4f,0.6f) ); break; // green
case TNS_GOOD: SetDiffuseColor( D3DXCOLOR(0.3f,0.8f,1.0f,0.6f) ); break;
case TNS_BOO: SetDiffuseColor( D3DXCOLOR(0.8f,0.0f,0.6f,0.6f) ); break;
case TNS_PERFECT: SetDiffuseColor( D3DXCOLOR(1.0f,1.0f,0.3f,1) ); break; // yellow
case TNS_GREAT: SetDiffuseColor( D3DXCOLOR(0.0f,1.0f,0.4f,1) ); break; // green
case TNS_GOOD: SetDiffuseColor( D3DXCOLOR(0.3f,0.8f,1.0f,1) ); break;
case TNS_BOO: SetDiffuseColor( D3DXCOLOR(0.8f,0.0f,0.6f,1) ); break;
case TNS_MISS: ASSERT( false ); break;
}
SetZoom( 1.0f );
+5 -5
View File
@@ -31,11 +31,11 @@ void GhostArrowBright::Step( TapNoteScore score )
{
switch( score )
{
case TNS_PERFECT: SetDiffuseColor( D3DXCOLOR(1.0f,1.0f,0.3f,1.0f) ); break; // yellow
case TNS_GREAT: SetDiffuseColor( D3DXCOLOR(0.0f,1.0f,0.4f,1.0f) ); break; // green
case TNS_GOOD: SetDiffuseColor( D3DXCOLOR(0.3f,0.8f,1.0f,1.0f) ); break;
case TNS_BOO: SetDiffuseColor( D3DXCOLOR(0.8f,0.0f,0.6f,1.0f) ); break;
case TNS_MISS: ASSERT( false ); break;
case TNS_PERFECT: SetDiffuseColor( D3DXCOLOR(1.0f,1.0f,0.3f,1) ); break; // yellow
case TNS_GREAT: SetDiffuseColor( D3DXCOLOR(0.0f,1.0f,0.4f,1) ); break; // green
case TNS_GOOD: SetDiffuseColor( D3DXCOLOR(0.3f,0.8f,1.0f,1) ); break;
case TNS_BOO: SetDiffuseColor( D3DXCOLOR(0.8f,0.0f,0.6f,1) ); break;
case TNS_MISS: ASSERT( false ); break;
}
SetState( 0 );
SetZoom( 1.0f );
+2 -2
View File
@@ -14,7 +14,7 @@
#include "GrayArrow.h"
#include "ThemeManager.h"
const float GRAY_ARROW_POP_UP_TIME = 0.3f;
const float GRAY_ARROW_POP_UP_TIME = 0.15f;
GrayArrow::GrayArrow()
@@ -32,7 +32,7 @@ void GrayArrow::SetBeat( const float fSongBeat )
void GrayArrow::Step()
{
SetZoom( 0.50 );
SetZoom( 0.75f );
BeginTweening( GRAY_ARROW_POP_UP_TIME );
SetTweenZoom( 1.0f );
}
+1 -1
View File
@@ -45,7 +45,7 @@ void LifeMeterBar::ChangeLife( TapNoteScore score )
case TNS_MISS: fDeltaLife = -0.080f; break;
}
if( IsHot() && score < TNS_GREAT )
if( IsHot() && score < TNS_GOOD )
fDeltaLife = -0.10f; // make it take a while to get back to "doing great"
m_fLifePercentage += fDeltaLife;
+14 -2
View File
@@ -62,7 +62,7 @@ MenuElements::MenuElements()
this->AddActor( &m_Invisible );
}
void MenuElements::Load( CString sBackgroundPath, CString sTopEdgePath, CString sHelpText )
void MenuElements::Load( CString sBackgroundPath, CString sTopEdgePath, CString sHelpText, bool bShowStyleIcon, bool bTimerEnabled, int iTimerSeconds )
{
LOG->WriteLine( "MenuElements::MenuElements()" );
@@ -80,13 +80,20 @@ void MenuElements::Load( CString sBackgroundPath, CString sTopEdgePath, CString
m_sprStyleIcon.StopAnimating();
m_sprStyleIcon.SetXY( STYLE_ICON_LOCAL_X, STYLE_ICON_LOCAL_Y );
m_sprStyleIcon.SetZ( -1 );
if( GAMEMAN->m_CurStyle == STYLE_NONE )
if( GAMEMAN->m_CurStyle == STYLE_NONE || !bShowStyleIcon )
m_sprStyleIcon.SetDiffuseColor( D3DXCOLOR(1,1,1,0) );
else
m_sprStyleIcon.SetState( GAMEMAN->m_CurStyle );
m_MenuTimer.SetXY( TIMER_LOCAL_X, TIMER_LOCAL_Y );
m_MenuTimer.SetZ( -1 );
if( !bTimerEnabled || !PREFSMAN->m_bMenuTimer )
{
m_MenuTimer.SetTimer( 99 );
m_MenuTimer.StopTimer();
}
else
m_MenuTimer.SetTimer( iTimerSeconds );
m_frameBottomBar.SetZ( -1 );
@@ -233,5 +240,10 @@ void MenuElements::DrawBottomLayer()
m_sprBG.Draw();
}
void MenuElements::StopTimer()
{
m_MenuTimer.StopTimer();
}
+4 -1
View File
@@ -33,7 +33,10 @@ public:
virtual void DrawPrimitives();
void Load( CString sBackgroundPath, CString sTopEdgePath, CString sHelpText );
void Load( CString sBackgroundPath, CString sTopEdgePath, CString sHelpText, bool bShowStyleIcon, bool bTimerEnabled, int iTimerSeconds );
void StallTimer();
void SetTimer( int iTimerSeconds );
void StopTimer();
void DrawTopLayer();
void DrawBottomLayer();
+21 -2
View File
@@ -15,12 +15,15 @@
#include "GameConstantsAndTypes.h"
#include "ThemeManager.h"
#include "ScreenManager.h"
#include "AnnouncerManager.h"
const float TIMER_SECONDS = 99;
MenuTimer::MenuTimer()
{
m_fSecondsLeft = TIMER_SECONDS;
m_fStallSeconds = 0;
m_bTimerStopped = false;
m_textDigit1.Load( THEME->GetPathTo(FONT_TIMER_NUMBERS) );
m_textDigit1.TurnShadowOff();
@@ -40,10 +43,21 @@ void MenuTimer::Update( float fDeltaTime )
{
ActorFrame::Update( fDeltaTime );
if( m_bTimerStopped )
return;
if( m_fStallSeconds > 0 )
{
m_fStallSeconds -= fDeltaTime;
return;
}
float fOldSecondsLeft = m_fSecondsLeft;
float fNewSecondsLeft = fOldSecondsLeft - fDeltaTime;
if( fOldSecondsLeft > 5 && fNewSecondsLeft < 5 ) // transition to below 5
if( fOldSecondsLeft > 5.5 && fNewSecondsLeft < 5.5 ) // transition to below 5.5
SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_MENU_HURRY_UP) );
else if( fOldSecondsLeft > 5 && fNewSecondsLeft < 5 ) // transition to below 5
{
m_textDigit1.SetEffectGlowing( 10, D3DXCOLOR(1,0,0,0), D3DXCOLOR(1,0,0,1) );
m_textDigit2.SetEffectGlowing( 10, D3DXCOLOR(1,0,0,0), D3DXCOLOR(1,0,0,1) );
@@ -80,10 +94,15 @@ void MenuTimer::Update( float fDeltaTime )
void MenuTimer::StopTimer()
{
m_bTimerStopped = true;
}
void MenuTimer::StallTimer()
{
m_fStallSeconds = 1;
}
void MenuTimer::SetTimer( int iSeconds )
{
m_fSecondsLeft = (float)iSeconds;
}
+4
View File
@@ -25,9 +25,13 @@ public:
virtual void Update( float fDeltaTime );
void StopTimer();
void StallTimer();
void SetTimer( int iTimerSeconds );
protected:
float m_fSecondsLeft;
float m_fStallSeconds;
bool m_bTimerStopped;
BitmapText m_textDigit1;
BitmapText m_textDigit2;
+7 -3
View File
@@ -23,7 +23,7 @@
const float FADE_TIME = 1.0f;
const float SWITCH_MUSIC_TIME = 0.15f;
const float SWITCH_MUSIC_TIME = 0.10f;
const float SAMPLE_MUSIC_DELAY = 0.20f;
const float ROULETTE_SWITCH_MUSIC_TIME = SWITCH_MUSIC_TIME/2;
const int ROULETTE_SWITCHES_IN_SLOWING_DOWN = 5;
@@ -924,6 +924,8 @@ void MusicWheel::PrevMusic( bool bSendSongChangedMessage )
if( fabsf(m_fPositionOffsetFromSelection) > 0.5f ) // wheel is busy spinning
return;
m_fTimeLeftBeforePlayMusicSample = 0;
switch( m_WheelState )
{
case STATE_SELECTING_MUSIC:
@@ -966,9 +968,11 @@ void MusicWheel::NextMusic( bool bSendSongChangedMessage )
return;
}
if( fabsf(m_fPositionOffsetFromSelection) > 0.5 ) // wheel is very busy spinning
if( fabsf(m_fPositionOffsetFromSelection) > 0.5f ) // wheel is very busy spinning
return;
m_fTimeLeftBeforePlayMusicSample = 0;
switch( m_WheelState )
{
case STATE_SELECTING_MUSIC:
@@ -1038,7 +1042,7 @@ bool MusicWheel::Select() // return true of a playable item was chosen
if( m_WheelState == STATE_ROULETTE_SPINNING )
{
m_WheelState = STATE_ROULETTE_SLOWING_DOWN;
m_iSwitchesLeftInSpinDown = ROULETTE_SWITCHES_IN_SLOWING_DOWN;
m_iSwitchesLeftInSpinDown = ROULETTE_SWITCHES_IN_SLOWING_DOWN/2+1 + rand()%(ROULETTE_SWITCHES_IN_SLOWING_DOWN/2);
m_fTimeLeftInState = 0.1f;
return false;
}
+50 -21
View File
@@ -134,13 +134,16 @@ CString NoteData::GetSMNoteDataString()
CStringArray asMeasureLines;
asMeasureLines.Add( ssprintf(" // measure %d", m+1) );
for( int i=iMeasureStartIndex; i<=iMeasureLastIndex; i+=iNoteIndexSpacing )
{
CString sLineString;
for( int c=0; c<m_iNumTracks; c++ )
sLineString += m_TapNotes[c][i];
asMeasureLines.Add( sLineString );
char szLineString[MAX_NOTE_TRACKS];
for( int t=0; t<m_iNumTracks; t++ )
szLineString[t] = m_TapNotes[t][i];
szLineString[t] = '\0';
asMeasureLines.Add( szLineString );
}
CString sMeasureString = join( "\n", asMeasureLines );
asMeasureStrings.Add( sMeasureString );
@@ -242,6 +245,7 @@ void NoteData::AddHoldNote( HoldNote add )
// add a tap note at the start of this hold
m_TapNotes[add.m_iTrack][add.m_iStartIndex] = '1';
ASSERT( m_iNumHoldNotes < MAX_HOLD_NOTES );
m_HoldNotes[m_iNumHoldNotes++] = add;
}
@@ -279,32 +283,57 @@ bool NoteData::IsThereANoteAtRow( int iRow )
}
int NoteData::GetLastRow()
int NoteData::GetFirstRow()
{
int iFirstIndexFoundSoFar = MAX_TAP_NOTE_ROWS-1;
int i;
for( i=0; i<MAX_TAP_NOTE_ROWS, i<iFirstIndexFoundSoFar; i++ ) // iterate back to front
{
if( !IsRowEmpty(i) )
{
iFirstIndexFoundSoFar = i;
break;
}
}
for( i=0; i<m_iNumHoldNotes; i++ )
{
if( m_HoldNotes[i].m_iStartIndex < iFirstIndexFoundSoFar )
iFirstIndexFoundSoFar = m_HoldNotes[i].m_iStartIndex;
}
return iFirstIndexFoundSoFar;
}
float NoteData::GetFirstBeat()
{
return NoteRowToBeat( GetFirstRow() );
}
int NoteData::GetLastRow()
{
int iOldestIndexFoundSoFar = 0;
int i;
for( i=MAX_TAP_NOTE_ROWS-1; i>=iOldestIndexFoundSoFar; i-- ) // iterate back to front
{
if( !IsRowEmpty(i) )
{
iOldestIndexFoundSoFar = i;
break;
}
}
for( i=0; i<m_iNumHoldNotes; i++ )
{
if( m_HoldNotes[i].m_iEndIndex > iOldestIndexFoundSoFar )
iOldestIndexFoundSoFar = m_HoldNotes[i].m_iEndIndex;
}
for( i=MAX_TAP_NOTE_ROWS-1; i>=iOldestIndexFoundSoFar; i-- ) // iterate back to front
{
for( int t=0; t<m_iNumTracks; t++ )
{
if( m_TapNotes[t][i] != '0' )
{
iOldestIndexFoundSoFar = i;
goto done_searching_tap_notes;
}
}
}
done_searching_tap_notes:
return iOldestIndexFoundSoFar;
}
@@ -623,8 +652,8 @@ void NoteData::MakeLittle()
void NoteData::Convert2sAnd3sToHoldNotes()
{
// Note that a 3 or a 1 can end a HoldNote.
// A 1 can end a HoldNote because it's easier for parsing DWIs
// Any note will end a hold (not just a '3'). This makes parsing DWIs much easier,
// plus we don't want tap notes in the middle of a hold!
for( int col=0; col<m_iNumTracks; col++ ) // foreach column
{
+3 -1
View File
@@ -48,7 +48,7 @@ public:
int m_iNumTracks;
TapNote m_TapNotes[MAX_NOTE_TRACKS][MAX_TAP_NOTE_ROWS];
HoldNote m_HoldNotes[MAX_HOLD_NOTE_ELEMENTS];
HoldNote m_HoldNotes[MAX_HOLD_NOTES];
int m_iNumHoldNotes;
void LoadFromSMNoteDataString( CString sSMNoteData );
@@ -73,6 +73,8 @@ public:
// statistics
bool IsThereANoteAtRow( int iRow );
float GetFirstBeat(); // return the beat number of the first note
int GetFirstRow();
float GetLastBeat(); // return the beat number of the last note
int GetLastRow();
int GetNumTapNotes( const float fStartBeat = 0, const float fEndBeat = MAX_BEATS );
+2 -2
View File
@@ -25,7 +25,7 @@ void NoteDataWithScoring::Init()
for( int i=0; i<MAX_TAP_NOTE_ROWS; i++ )
m_TapNoteScores[t][i] = TNS_NONE;
for( int i=0; i<MAX_HOLD_NOTE_ELEMENTS; i++ )
for( int i=0; i<MAX_HOLD_NOTES; i++ )
m_HoldNoteScores[i] = HNS_NONE;
}
@@ -139,7 +139,7 @@ float NoteDataWithScoring::GetActualChaosRadarValue( float fSongSeconds )
iNumChaosNotesCompleted++;
}
float fReturn = iNumChaosNotesCompleted / fSongSeconds * 0.5;
float fReturn = iNumChaosNotesCompleted / fSongSeconds * 0.5f;
return min( fReturn, 1.0f );
}
+1 -1
View File
@@ -20,7 +20,7 @@ struct NoteDataWithScoring : public NoteData
// maintain this extra data in addition to the NoteData
TapNoteScore m_TapNoteScores[MAX_NOTE_TRACKS][MAX_TAP_NOTE_ROWS];
HoldNoteScore m_HoldNoteScores[MAX_HOLD_NOTE_ELEMENTS];
HoldNoteScore m_HoldNoteScores[MAX_HOLD_NOTES];
// statistics
+9 -5
View File
@@ -61,7 +61,7 @@ void NoteField::Load( NoteData* pNoteData, PlayerNumber p, StyleDef* pStyleDef,
}
for( int i=0; i<MAX_HOLD_NOTE_ELEMENTS; i++ )
for( int i=0; i<MAX_HOLD_NOTES; i++ )
m_HoldNoteLife[i] = 1; // start with full life
@@ -223,10 +223,10 @@ void NoteField::DrawPrimitives()
//
// Freeze text
//
CArray<FreezeSegment,FreezeSegment&> &aFreezeSegments = SONGMAN->GetCurrentSong()->m_FreezeSegments;
for( i=0; i<aFreezeSegments.GetSize(); i++ )
CArray<StopSegment,StopSegment&> &aStopSegments = SONGMAN->GetCurrentSong()->m_StopSegments;
for( i=0; i<aStopSegments.GetSize(); i++ )
{
DrawFreezeText( BeatToNoteRow(aFreezeSegments[i].m_fStartBeat), aFreezeSegments[i].m_fFreezeSeconds );
DrawFreezeText( BeatToNoteRow(aStopSegments[i].m_fStartBeat), aStopSegments[i].m_fStopSeconds );
}
//
@@ -266,6 +266,7 @@ void NoteField::DrawPrimitives()
for( int i=0; i<m_iNumHoldNotes; i++ )
{
HoldNote &hn = m_HoldNotes[i];
const float fLife = m_HoldNoteLife[i];
if( hn.m_iTrack != c ) // this HoldNote doesn't belong to this column
continue;
@@ -280,7 +281,7 @@ void NoteField::DrawPrimitives()
// If this note was in the past and has life > 0, then it was completed and don't draw it!
if( hn.m_iEndIndex < BeatToNoteRow(m_fSongBeat) && m_HoldNoteLife[i] > 0 )
if( hn.m_iEndIndex < BeatToNoteRow(m_fSongBeat) && fLife > 0 )
continue; // skip
@@ -298,6 +299,9 @@ void NoteField::DrawPrimitives()
if( j < iIndexFirstArrowToDraw || iIndexLastArrowToDraw < j)
continue; // skip this arrow
if( fLife > 0 && NoteRowToBeat(j) < m_fSongBeat )
continue;
CreateHoldNoteInstance( instances[iCount++], bActive, (float)j, hn, fHoldNoteLife );
}
+1 -1
View File
@@ -41,7 +41,7 @@ public:
void RemoveTapNoteRow( int iIndex );
void SetHoldNoteLife( int iIndex, float fLife );
float m_HoldNoteLife[MAX_HOLD_NOTE_ELEMENTS]; // 1.0 = full life, 0 = dead
float m_HoldNoteLife[MAX_HOLD_NOTES]; // 1.0 = full life, 0 = dead
float m_fBeginMarker, m_fEndMarker; // only used with MODE_EDIT
+75 -44
View File
@@ -114,8 +114,8 @@ bool Notes::LoadFromBMSFile( const CString &sPath )
{
LOG->WriteLine( "Notes::LoadFromBMSFile( '%s' )", sPath );
NoteData tempNoteData;
tempNoteData.m_iNumTracks = MAX_NOTE_TRACKS;
NoteData* pNoteData = new NoteData;
pNoteData->m_iNumTracks = MAX_NOTE_TRACKS;
CStdioFile file;
if( !file.Open( sPath, CFile::modeRead|CFile::shareDenyNone ) )
@@ -228,7 +228,7 @@ bool Notes::LoadFromBMSFile( const CString &sPath )
mapBMSTrackToDanceNote( iTrackNum, iColumnNumber, cNoteChar );
if( iColumnNumber != -1 )
tempNoteData.m_TapNotes[iColumnNumber][iNoteIndex] = cNoteChar;
pNoteData->m_TapNotes[iColumnNumber][iNoteIndex] = cNoteChar;
}
}
}
@@ -241,14 +241,14 @@ bool Notes::LoadFromBMSFile( const CString &sPath )
for( int i=0; i<MAX_TAP_NOTE_ROWS; i++ ) // for each TapNote
{
memcpy(
tempNoteData.m_TapNotes[DANCE_NOTE_PAD1_UP],
tempNoteData.m_TapNotes[DANCE_NOTE_PAD1_UPRIGHT],
MAX_TAP_NOTE_ROWS*sizeof(tempNoteData.m_TapNotes[0][0])
pNoteData->m_TapNotes[DANCE_NOTE_PAD1_UP],
pNoteData->m_TapNotes[DANCE_NOTE_PAD1_UPRIGHT],
MAX_TAP_NOTE_ROWS*sizeof(pNoteData->m_TapNotes[0][0])
);
memcpy(
tempNoteData.m_TapNotes[DANCE_NOTE_PAD2_UP],
tempNoteData.m_TapNotes[DANCE_NOTE_PAD2_UPRIGHT],
MAX_TAP_NOTE_ROWS*sizeof(tempNoteData.m_TapNotes[0][0])
pNoteData->m_TapNotes[DANCE_NOTE_PAD2_UP],
pNoteData->m_TapNotes[DANCE_NOTE_PAD2_UPRIGHT],
MAX_TAP_NOTE_ROWS*sizeof(pNoteData->m_TapNotes[0][0])
);
}
}
@@ -288,11 +288,14 @@ bool Notes::LoadFromBMSFile( const CString &sPath )
throw RageException( "Invalid NotesType." );
}
NoteData tempNoteData2;
tempNoteData2.m_iNumTracks = iNumNewTracks;
tempNoteData2.LoadTransformed( &tempNoteData, iNumNewTracks, iTransformNewToOld );
NoteData* pNoteData2 = new NoteData;
pNoteData2->m_iNumTracks = iNumNewTracks;
pNoteData2->LoadTransformed( pNoteData, iNumNewTracks, iTransformNewToOld );
m_sSMNoteData = tempNoteData2.GetSMNoteDataString();
m_sSMNoteData = pNoteData2->GetSMNoteDataString();
delete pNoteData;
delete pNoteData2;
TidyUpData();
@@ -370,15 +373,16 @@ bool Notes::LoadFromDWITokens(
CMap<int, int, int, int> mapDanceNoteToNoteDataColumn;
if( m_NotesType == NOTES_TYPE_DANCE_SINGLE )
switch( m_NotesType )
{
case NOTES_TYPE_DANCE_SINGLE:
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 3;
}
else if( m_NotesType == NOTES_TYPE_DANCE_DOUBLE || m_NotesType == NOTES_TYPE_DANCE_COUPLE )
{
break;
case NOTES_TYPE_DANCE_DOUBLE:
case NOTES_TYPE_DANCE_COUPLE:
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2;
@@ -387,18 +391,18 @@ bool Notes::LoadFromDWITokens(
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_DOWN] = 5;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_UP] = 6;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_RIGHT] = 7;
}
else if( m_NotesType == NOTES_TYPE_DANCE_SOLO )
{
break;
case NOTES_TYPE_DANCE_SOLO:
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPLEFT] = 1;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 2;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 3;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPRIGHT] = 4;
mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 5;
}
else
break;
default:
ASSERT(0);
}
m_sDescription = sDescription;
@@ -406,8 +410,10 @@ bool Notes::LoadFromDWITokens(
//m_DifficultyClass = DifficultyClassFromDescriptionAndMeter( m_sDescription, m_iMeter );
NoteData tempNoteData;
tempNoteData.m_iNumTracks = mapDanceNoteToNoteDataColumn.GetCount();
NoteData* pNoteData = new NoteData;
ASSERT( pNoteData );
printf( "sizeof NoteData = %d\n", sizeof(NoteData) );
pNoteData->m_iNumTracks = mapDanceNoteToNoteDataColumn.GetCount();
for( int pad=0; pad<2; pad++ ) // foreach pad
{
@@ -428,6 +434,7 @@ bool Notes::LoadFromDWITokens(
double fCurrentBeat = 0;
double fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
for( int i=0; i<sStepData.GetLength(); )
{
char c = sStepData[i++];
@@ -473,45 +480,47 @@ bool Notes::LoadFromDWITokens(
if( note1 != DANCE_NOTE_NONE )
{
int iCol1 = mapDanceNoteToNoteDataColumn[note1];
tempNoteData.m_TapNotes[iCol1][iIndex] = '2';
pNoteData->m_TapNotes[iCol1][iIndex] = '2';
}
if( note2 != DANCE_NOTE_NONE )
{
int iCol2 = mapDanceNoteToNoteDataColumn[note2];
tempNoteData.m_TapNotes[iCol2][iIndex] = '2';
pNoteData->m_TapNotes[iCol2][iIndex] = '2';
}
}
break;
default: // this is a note character
{
int iIndex = BeatToNoteRow( (float)fCurrentBeat );
int iIndex = BeatToNoteRow( (float)fCurrentBeat );
DanceNote note1, note2;
DWIcharToNote( c, (InstrumentNumber)pad, note1, note2 );
DanceNote note1, note2;
DWIcharToNote( c, (InstrumentNumber)pad, note1, note2 );
if( note1 != DANCE_NOTE_NONE )
{
int iCol1 = mapDanceNoteToNoteDataColumn[note1];
tempNoteData.m_TapNotes[iCol1][iIndex] = '1';
}
if( note2 != DANCE_NOTE_NONE )
{
int iCol2 = mapDanceNoteToNoteDataColumn[note2];
tempNoteData.m_TapNotes[iCol2][iIndex] = '1';
}
if( note1 != DANCE_NOTE_NONE )
{
int iCol1 = mapDanceNoteToNoteDataColumn[note1];
pNoteData->m_TapNotes[iCol1][iIndex] = '1';
}
if( note2 != DANCE_NOTE_NONE )
{
int iCol2 = mapDanceNoteToNoteDataColumn[note2];
pNoteData->m_TapNotes[iCol2][iIndex] = '1';
}
fCurrentBeat += fCurrentIncrementer;
fCurrentBeat += fCurrentIncrementer;
}
break;
}
}
}
tempNoteData.Convert2sAnd3sToHoldNotes(); // this will expand the HoldNote begin markers we wrote into actual HoldNotes
pNoteData->Convert2sAnd3sToHoldNotes(); // this will expand the HoldNote begin markers we wrote into actual HoldNotes
ASSERT( tempNoteData.m_iNumTracks > 0 );
ASSERT( pNoteData->m_iNumTracks > 0 );
m_sSMNoteData = tempNoteData.GetSMNoteDataString();
m_sSMNoteData = pNoteData->GetSMNoteDataString();
delete pNoteData;
TidyUpData();
@@ -628,6 +637,28 @@ DifficultyClass Notes::DifficultyClassFromDescriptionAndMeter( CString sDescript
//
//////////////////////////////////////////////
int CompareNotesPointersByRadarValues(const void *arg1, const void *arg2)
{
Notes* pNotes1 = *(Notes**)arg1;
Notes* pNotes2 = *(Notes**)arg2;
float fScore1 = 0;
float fScore2 = 0;
for( int r=0; r<NUM_RADAR_VALUES; r++ )
{
fScore1 += pNotes1->m_fRadarValues[r];
fScore2 += pNotes2->m_fRadarValues[r];
}
if( fScore1 < fScore2 )
return -1;
else if( fScore1 == fScore2 )
return 0;
else
return 1;
}
int CompareNotesPointersByMeter(const void *arg1, const void *arg2)
{
Notes* pNotes1 = *(Notes**)arg1;
@@ -639,7 +670,7 @@ int CompareNotesPointersByMeter(const void *arg1, const void *arg2)
if( iScore1 < iScore2 )
return -1;
else if( iScore1 == iScore2 )
return 0;
return CompareNotesPointersByRadarValues( arg1, arg2 );
else
return 1;
}
+10 -5
View File
@@ -249,8 +249,6 @@ void Player::HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff )
ASSERT( col >= 0 && col <= m_iNumTracks );
m_GrayArrowRow.Step( col );
// look for the closest matching step
int iIndexStartLookingAt = BeatToNoteRow( fSongBeat );
@@ -294,6 +292,8 @@ void Player::HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff )
}
}
bool bDestroyedNote = false;
if( iIndexOverlappingNote != -1 )
{
// compute the score for this hit
@@ -303,11 +303,13 @@ void Player::HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff )
TapNoteScore &score = m_TapNoteScores[col][iIndexOverlappingNote];
if( fPercentFromPerfect < 0.30f ) score = TNS_PERFECT;
else if( fPercentFromPerfect < 0.55f ) score = TNS_GREAT;
else if( fPercentFromPerfect < 0.78f ) score = TNS_GOOD;
if( fPercentFromPerfect < 0.25f ) score = TNS_PERFECT;
else if( fPercentFromPerfect < 0.50f ) score = TNS_GREAT;
else if( fPercentFromPerfect < 0.75f ) score = TNS_GOOD;
else score = TNS_BOO;
bDestroyedNote = score >= TNS_GOOD;
bool bRowDestroyed = true;
for( int t=0; t<m_iNumTracks; t++ ) // did this complete the elminiation of the row?
@@ -322,6 +324,9 @@ void Player::HandlePlayerStep( float fSongBeat, int col, float fMaxBeatDiff )
if( bRowDestroyed )
OnRowDestroyed( fSongBeat, col, fMaxBeatDiff, iIndexOverlappingNote );
}
if( !bDestroyedNote )
m_GrayArrowRow.Step( col );
}
void Player::OnRowDestroyed( float fSongBeat, int col, float fMaxBeatDiff, int iIndexThatWasSteppedOn )
+17 -8
View File
@@ -25,12 +25,13 @@ PrefsManager::PrefsManager()
m_bHighTextureDetail = false;
m_bIgnoreJoyAxes = false;
m_bShowFPS = false;
m_visMode = VIS_MODE_ANIMATION;
m_bAnnouncer = true;
m_BackgroundMode = BGMODE_ANIMATIONS;
m_fBGBrightness = 0.8f;
m_bMenuTimer = true;
m_bEventMode = false;
m_iNumArcadeStages = 3;
m_bAutoPlay = false;
m_fJudgeWindow = 0.12f;
m_fJudgeWindow = 0.18f;
for( int p=0; p<NUM_PLAYERS; p++ )
m_PreferredDifficultyClass[p] = CLASS_EASY;
@@ -58,13 +59,17 @@ void PrefsManager::ReadPrefsFromDisk()
ini.GetValueB( "Options", "HighTextureDetail", m_bHighTextureDetail );
ini.GetValueB( "Options", "IgnoreJoyAxes", m_bIgnoreJoyAxes );
ini.GetValueB( "Options", "ShowFPS", m_bShowFPS );
ini.GetValueI( "Options", "VisMode", m_visMode );
ini.GetValueB( "Options", "Announcer", m_bAnnouncer );
ini.GetValueI( "Options", "BackgroundMode", (int&)m_BackgroundMode );
ini.GetValueF( "Options", "BGBrightness", m_fBGBrightness );
ini.GetValueB( "Options", "MenuTimer", m_bMenuTimer );
ini.GetValueB( "Options", "EventMode", m_bEventMode );
ini.GetValueI( "Options", "NumArcadeStages", m_iNumArcadeStages );
ini.GetValueB( "Options", "AutoPlay", m_bAutoPlay );
ini.GetValueF( "Options", "JudgeWindow", m_fJudgeWindow );
ini.GetValue( "Options", "Announer", m_sAnnouncer );
ini.GetValue( "Options", "NoteSkin", m_sNoteSkin );
CString sAdditionalSongFolders;
ini.GetValue( "Options", "SongFolders", sAdditionalSongFolders );
split( sAdditionalSongFolders, ",", m_asSongFolders, true );
@@ -81,13 +86,17 @@ void PrefsManager::SavePrefsToDisk()
ini.SetValueB( "Options", "HighTextureDetail", m_bHighTextureDetail );
ini.SetValueB( "Options", "IgnoreJoyAxes", m_bIgnoreJoyAxes );
ini.SetValueB( "Options", "ShowFPS", m_bShowFPS );
ini.SetValueI( "Options", "VisMode", m_visMode );
ini.SetValueB( "Options", "Announcer", m_bAnnouncer );
ini.SetValueI( "Options", "BackgroundMode", m_BackgroundMode);
ini.SetValueF( "Options", "BGBrightness", m_fBGBrightness );
ini.SetValueB( "Options", "EventMode", m_bEventMode );
ini.SetValueB( "Options", "MenuTimer", m_bMenuTimer );
ini.SetValueI( "Options", "NumArcadeStages", m_iNumArcadeStages );
ini.SetValueB( "Options", "AutoPlay", m_bAutoPlay );
ini.SetValueF( "Options", "JudgeWindow", m_fJudgeWindow );
ini.SetValue( "Options", "Announer", m_sAnnouncer );
ini.SetValue( "Options", "NoteSkin", m_sNoteSkin );
ini.SetValue( "Options", "SongFolders", join(",", m_asSongFolders) );
ini.WriteFile();
+11 -10
View File
@@ -18,31 +18,32 @@
const int NUM_PAD_TO_DEVICE_SLOTS = 3; // three device inputs may map to one pad input
enum VisualizationMode {
VIS_MODE_NONE = 0,
VIS_MODE_ANIMATION,
VIS_MODE_MOVIE,
};
class PrefsManager
{
public:
PrefsManager();
~PrefsManager();
// Options that ARE saved between sessions
enum BackgroundMode { BGMODE_OFF, BGMODE_ANIMATIONS, BGMODE_MOVIEVIS };
// GameOptions (ARE saved between sessions)
bool m_bWindowed;
bool m_bHighDetail;
bool m_bHighTextureDetail;
bool m_bIgnoreJoyAxes;
bool m_bShowFPS;
int m_visMode;
bool m_bAnnouncer;
BackgroundMode m_BackgroundMode;
float m_fBGBrightness;
bool m_bMenuTimer;
bool m_bEventMode;
int m_iNumArcadeStages;
bool m_bAutoPlay;
float m_fJudgeWindow;
// AppearanceOptions (ARE saved between sessions)
CString m_sAnnouncer;
CString m_sNoteSkin;
CStringArray m_asSongFolders;
void ReadPrefsFromDisk();
+29 -20
View File
@@ -143,30 +143,39 @@ void RageBitmapTexture::Create(
bStretch |= ddii.Width > dwMaxSize || ddii.Height > dwMaxSize;
/*
// HACK: The stupid Savage driver will report that it can hold the entire texture,
// then allocate something smaller than the dimensions we need!
// after allocating the texture, make sure it's the size we expect. If not,
// load it again with scaling turned on.
// HACK: On a Voodoo3 and Win98, D3DXCreateTextureFromFileEx sometimes fails for no good reason.
// So, we'll try the call 2x in a row in case the first one fails
*/
// I'm taking out the Savage hack because it's causing problems. Tough luck for them. I think
// the problem can be worked around by setting MaxTextureSize to 512.
if( FAILED( hr = D3DXCreateTextureFromFileEx(
m_pd3dDevice, // device
m_sFilePath, // soure file
bStretch ? dwMaxSize : D3DX_DEFAULT, // width
bStretch ? dwMaxSize : D3DX_DEFAULT, // height
iMipMaps, // mip map levels
0, // usage (is a render target?)
fmtTexture, // our preferred texture format
D3DPOOL_MANAGED, // which memory pool
(bStretch ? D3DX_FILTER_BOX : D3DX_FILTER_NONE) | (bDither ? D3DX_FILTER_DITHER : 0), // filter
D3DX_FILTER_BOX | (bDither ? D3DX_FILTER_DITHER : 0), // mip filter
0, // no color key
&ddii, // struct to fill with source image info
NULL, // no palette
&m_pd3dTexture ) ) )
for( int i=0; i<2; i++ )
{
throw RageException( hr, "D3DXCreateTextureFromFileEx() failed for file '%s'.", m_sFilePath );
if( FAILED( hr = D3DXCreateTextureFromFileEx(
m_pd3dDevice, // device
m_sFilePath, // soure file
bStretch ? dwMaxSize : D3DX_DEFAULT, // width
bStretch ? dwMaxSize : D3DX_DEFAULT, // height
iMipMaps, // mip map levels
0, // usage (is a render target?)
fmtTexture, // our preferred texture format
D3DPOOL_MANAGED, // which memory pool
(bStretch ? D3DX_FILTER_BOX : D3DX_FILTER_NONE) | (bDither ? D3DX_FILTER_DITHER : 0), // filter
D3DX_FILTER_BOX | (bDither ? D3DX_FILTER_DITHER : 0), // mip filter
0, // no color key
&ddii, // struct to fill with source image info
NULL, // no palette
&m_pd3dTexture ) ) )
{
if( i==0 )
{
LOG->WriteLine( "WARNING! D3DXCreateTextureFromFileEx failed. Sleep and try one more time..." );
::Sleep( 10 );
continue;
}
throw RageException( hr, "D3DXCreateTextureFromFileEx() failed for file '%s'.", m_sFilePath );
}
else
break;
}
/////////////////////
+1 -1
View File
@@ -242,7 +242,7 @@ bool RageDisplay::SwitchDisplayMode(
// device is not yet created. We need to create it
if( FAILED( hr = m_pd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
m_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
&m_d3dpp, &m_pd3dDevice) ) )
{
LOG->WriteLineHr( hr, "failed to create device: %d, %u, %u, %u.", bWindowed, dwWidth, dwHeight, dwBPP );
+19 -2
View File
@@ -426,13 +426,13 @@ HRESULT RageMovieTexture::CreateD3DTexture()
// Create the texture that maps to this media type
//////////////////////////////////////////////////
if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice,
m_iSourceHeight, m_iSourceHeight,
m_iSourceWidth, m_iSourceHeight,
1, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pd3dTexture[0] ) ) )
throw RageException( hr, "Could not create the D3DX texture!" );
if( FAILED( hr = D3DXCreateTexture(m_pd3dDevice,
m_iSourceHeight, m_iSourceHeight,
m_iSourceWidth, m_iSourceHeight,
1, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pd3dTexture[1] ) ) )
throw RageException( hr, "Could not create the D3DX texture!" );
@@ -491,3 +491,20 @@ void RageMovieTexture::CleanupDShow()
if (m_pGB) m_pGB.Release ();
}
void RageMovieTexture::Play()
{
PlayMovie();
}
void RageMovieTexture::SetPosition( float fSeconds )
{
m_pMP->put_CurrentPosition(0);
}
void RageMovieTexture::Pause()
{
HRESULT hr;
if( FAILED( hr = m_pMC->Pause() ) )
throw RageException( hr, "Could not pause the DirectShow graph." );
}
+3
View File
@@ -96,6 +96,9 @@ public:
);
LPDIRECT3DTEXTURE8 GetD3DTexture();
virtual void Play();
virtual void SetPosition( float fSeconds );
virtual void Pause();
LPDIRECT3DTEXTURE8 m_pd3dTexture[2]; // double buffered
int m_iIndexActiveTexture; // either 0 or 1
+4 -1
View File
@@ -41,7 +41,7 @@ RageSound::RageSound( HWND hWnd )
"The most likely cause of this problem is that you do not have a sound card\n"
"installed, or that you have not yet installed a driver for your sound card.\n"
"Before running this program again, please verify that your sound card is\n"
"is working in other Screens applications."
"is working in other applications."
);
}
@@ -93,6 +93,9 @@ void RageSound::PlayOnceStreamed( CString sPath )
void RageSound::PlayOnceStreamedFromDir( CString sDir )
{
if( sDir == "" )
return;
// make sure there's a backslash at the end of this path
if( sDir[sDir.GetLength()-1] != '\\' )
sDir += "\\";
+3
View File
@@ -60,6 +60,9 @@ public:
) = 0;
virtual LPDIRECT3DTEXTURE8 GetD3DTexture() = 0;
virtual void Play() {};
virtual void SetPosition( float fSeconds ) {};
virtual void Pause() {};
int GetSourceWidth() {return m_iSourceWidth;};
int GetSourceHeight() {return m_iSourceHeight;};
+2
View File
@@ -28,6 +28,8 @@ public:
void SetPrefs( const DWORD dwMaxSize, const DWORD dwTextureColorDepth )
{
if( dwMaxSize == m_iMaxTextureSize && dwTextureColorDepth == m_iTextureColorDepth )
return;
ASSERT( m_iMaxTextureSize >= 64 );
m_iMaxTextureSize = dwMaxSize;
m_iTextureColorDepth = dwTextureColorDepth;
+14 -7
View File
@@ -347,16 +347,23 @@ DWORD GetFileSizeInBytes( const CString &sFilePath )
bool DoesFileExist( const CString &sPath )
{
//LOG->WriteLine( "DoesFileExist(%s)", sPath );
DWORD dwAttr = GetFileAttributes( sPath );
if( dwAttr == (DWORD)-1 )
return FALSE;
else
return TRUE;
return bool(dwAttr != (DWORD)-1);
}
bool IsAFile( const CString &sPath )
{
return DoesFileExist(sPath) && ! IsADirectory(sPath);
}
bool IsADirectory( const CString &sPath )
{
DWORD dwAttr = GetFileAttributes( sPath );
return (dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
int CompareCStringsAsc(const void *arg1, const void *arg2)
{
CString str1 = *(CString *)arg1;
+2
View File
@@ -102,6 +102,8 @@ int GetHashForFile( CString sPath );
int GetHashForDirectory( CString sDir ); // a hash value that remains the same as long as nothing in the directory has changed
bool DoesFileExist( const CString &sPath );
bool IsAFile( const CString &sPath );
bool IsADirectory( const CString &sPath );
DWORD GetFileSizeInBytes( const CString &sFilePath );
int CompareCStringsAsc(const void *arg1, const void *arg2);
+138
View File
@@ -0,0 +1,138 @@
#include "stdafx.h"
/*
-----------------------------------------------------------------------------
Class: ScreenAppearanceOptions
Desc: See header.
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
Chris Danford
-----------------------------------------------------------------------------
*/
#include "ScreenAppearanceOptions.h"
#include <assert.h>
#include "RageTextureManager.h"
#include "RageUtil.h"
#include "RageMusic.h"
#include "ScreenManager.h"
#include "PrefsManager.h"
#include "ScreenOptions.h"
#include "ScreenTitleMenu.h"
#include "GameConstantsAndTypes.h"
#include "StepMania.h"
#include "ThemeManager.h"
#include "RageLog.h"
#include "AnnouncerManager.h"
#include "GameManager.h"
enum {
AO_ANNOUNCER = 0,
AO_SKIN,
NUM_APPEARANCE_OPTIONS_LINES
};
OptionLineData g_AppearanceOptionsLines[NUM_APPEARANCE_OPTIONS_LINES] = {
{ "Announcer", 1, {"OFF"} }, // fill this in on ImportOptions()
{ "Note Skin", 0, {""} }, // fill this in on ImportOptions()
};
ScreenAppearanceOptions::ScreenAppearanceOptions() :
ScreenOptions(
THEME->GetPathTo(GRAPHIC_PLAYER_OPTIONS_BACKGROUND),
THEME->GetPathTo(GRAPHIC_PLAYER_OPTIONS_TOP_EDGE)
)
{
LOG->WriteLine( "ScreenAppearanceOptions::ScreenAppearanceOptions()" );
Init(
INPUTMODE_BOTH,
g_AppearanceOptionsLines,
NUM_APPEARANCE_OPTIONS_LINES
);
m_Menu.StopTimer();
}
void ScreenAppearanceOptions::ImportOptions()
{
// fill in announcer names
CStringArray arrayAnnouncerNames;
ANNOUNCER->GetAnnouncerNames( arrayAnnouncerNames );
m_OptionLineData[AO_ANNOUNCER].iNumOptions = arrayAnnouncerNames.GetSize() + 1;
for( int i=0; i<arrayAnnouncerNames.GetSize(); i++ )
strcpy( m_OptionLineData[AO_ANNOUNCER].szOptionsText[i+1], arrayAnnouncerNames[i] );
// highlight currently selected announcer
m_iSelectedOption[0][AO_ANNOUNCER] = -1;
for( i=1; i<m_OptionLineData[AO_ANNOUNCER].iNumOptions; i++ )
{
if( stricmp(m_OptionLineData[AO_ANNOUNCER].szOptionsText[i], ANNOUNCER->GetCurrentAnnouncerName())==0 )
{
m_iSelectedOption[0][AO_ANNOUNCER] = i;
break;
}
}
if( m_iSelectedOption[0][AO_ANNOUNCER] == -1 )
m_iSelectedOption[0][AO_ANNOUNCER] = 0;
// fill in skin names
CStringArray arraySkinNames;
GAMEMAN->GetSkinNames( arraySkinNames );
m_OptionLineData[AO_SKIN].iNumOptions = arraySkinNames.GetSize();
for( i=0; i<arraySkinNames.GetSize(); i++ )
strcpy( m_OptionLineData[AO_SKIN].szOptionsText[i], arraySkinNames[i] );
// highlight currently selected skin
m_iSelectedOption[0][AO_SKIN] = -1;
for( i=0; i<m_OptionLineData[AO_SKIN].iNumOptions; i++ )
{
if( stricmp(m_OptionLineData[AO_SKIN].szOptionsText[i], GAMEMAN->m_sCurrentSkin)==0 )
{
m_iSelectedOption[0][AO_SKIN] = i;
break;
}
}
if( m_iSelectedOption[0][AO_SKIN] == -1 )
m_iSelectedOption[0][AO_SKIN] = 0;
}
void ScreenAppearanceOptions::ExportOptions()
{
int iSelectedAnnouncer = m_iSelectedOption[0][AO_ANNOUNCER];
CString sNewAnnouncer = m_OptionLineData[AO_ANNOUNCER].szOptionsText[iSelectedAnnouncer];
if( iSelectedAnnouncer == 0 )
sNewAnnouncer = "";
PREFSMAN->m_sAnnouncer = sNewAnnouncer;
ANNOUNCER->SwitchAnnouncer( sNewAnnouncer );
int iSelectedSkin = m_iSelectedOption[0][AO_SKIN];
CString sNewSkin = m_OptionLineData[AO_SKIN].szOptionsText[iSelectedSkin];
PREFSMAN->m_sNoteSkin = sNewSkin;
GAMEMAN->m_sCurrentSkin = sNewSkin;
}
void ScreenAppearanceOptions::GoToPrevState()
{
SCREENMAN->SetNewScreen( new ScreenTitleMenu );
PREFSMAN->SavePrefsToDisk();
}
void ScreenAppearanceOptions::GoToNextState()
{
SCREENMAN->SetNewScreen( new ScreenTitleMenu );
PREFSMAN->SavePrefsToDisk();
}
+32
View File
@@ -0,0 +1,32 @@
/*
-----------------------------------------------------------------------------
Class: ScreenAppearanceOptions
Desc: Select a theme and announcer.
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
Chris Danford
-----------------------------------------------------------------------------
*/
#include "Screen.h"
#include "ScreenOptions.h"
#include "Sprite.h"
#include "BitmapText.h"
#include "RandomSample.h"
#include "TransitionFade.h"
#include "Quad.h"
class ScreenAppearanceOptions : public ScreenOptions
{
public:
ScreenAppearanceOptions();
private:
void ImportOptions();
void ExportOptions();
void GoToNextState();
void GoToPrevState();
};
+1 -2
View File
@@ -54,8 +54,7 @@ void ScreenCaution::HandleScreenMessage( const ScreenMessage SM )
m_Wipe.CloseWipingRight( SM_GoToSelectMusic );
break;
case SM_DoneOpening:
if( PREFSMAN->m_bAnnouncer )
SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_CAUTION) );
SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_CAUTION) );
break;
case SM_GoToSelectMusic:
SCREENMAN->SetNewScreen( new ScreenSelectStyle );
+53 -34
View File
@@ -93,7 +93,7 @@ ScreenEdit::ScreenEdit()
if( m_pNotes == NULL )
{
m_pNotes = new Notes;
m_pSong->m_arrayNotes.Add( m_pNotes );
m_pSong->m_apNotes.Add( m_pNotes );
}
NoteData noteData;
@@ -165,7 +165,7 @@ ScreenEdit::ScreenEdit()
m_soundInvalid.Load( THEME->GetPathTo(SOUND_MENU_INVALID) );
m_soundMusic.Load( m_pSong->GetMusicPath() );
m_soundMusic.Load( m_pSong->GetMusicPath(), true ); // enable accurate sync
m_soundMusic.SetPlaybackRate( 0.5f );
@@ -402,20 +402,19 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
}
break;
case DIK_ESCAPE:
m_pSong->LoadFromSMFile( m_pSong->GetCacheFilePath() );
SCREENMAN->SetNewScreen( new ScreenEditMenu );
break;
case DIK_S:
{
// copy edit into current Notes
Notes* pNotes;
pNotes = SONGMAN->GetCurrentNotes(PLAYER_1);
Song* pSong = SONGMAN->GetCurrentSong();
Notes* pNotes = SONGMAN->GetCurrentNotes(PLAYER_1);
if( pNotes == NULL )
{
// allocate a new Notes
SONGMAN->GetCurrentSong()->m_arrayNotes.SetSize( SONGMAN->GetCurrentSong()->m_arrayNotes.GetSize() + 1 );
pNotes = SONGMAN->GetCurrentSong()->m_arrayNotes[ SONGMAN->GetCurrentSong()->m_arrayNotes.GetSize()-1 ];
pNotes = new Notes;
pSong->m_apNotes.Add( pNotes );
pNotes->m_NotesType = GAMEMAN->m_CurNotesType;
pNotes->m_sDescription = "Untitled";
pNotes->m_iMeter = 1;
@@ -664,12 +663,15 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
float fDeltaBPM;
switch( DeviceI.button )
{
case DIK_F7: fDeltaBPM = - 0.025f; break;
case DIK_F8: fDeltaBPM = + 0.025f; break;
case DIK_F7: fDeltaBPM = - 0.020f; break;
case DIK_F8: fDeltaBPM = + 0.020f; break;
default: ASSERT(0);
}
if( type == IET_FAST_REPEAT )
fDeltaBPM *= 40;
switch( type )
{
case IET_SLOW_REPEAT: fDeltaBPM *= 10; break;
case IET_FAST_REPEAT: fDeltaBPM *= 40; break;
}
float fNewBPM = fBPM + fDeltaBPM;
for( int i=0; i<m_pSong->m_BPMSegments.GetSize(); i++ )
@@ -696,30 +698,33 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
float fFreezeDelta;
switch( DeviceI.button )
{
case DIK_F9: fFreezeDelta = -0.025f; break;
case DIK_F10: fFreezeDelta = +0.025f; break;
case DIK_F9: fFreezeDelta = -0.020f; break;
case DIK_F10: fFreezeDelta = +0.020f; break;
default: ASSERT(0);
}
if( type == IET_FAST_REPEAT )
fFreezeDelta *= 40;
for( int i=0; i<m_pSong->m_FreezeSegments.GetSize(); i++ )
switch( type )
{
if( m_pSong->m_FreezeSegments[i].m_fStartBeat == m_fBeat )
case IET_SLOW_REPEAT: fFreezeDelta *= 10; break;
case IET_FAST_REPEAT: fFreezeDelta *= 40; break;
}
for( int i=0; i<m_pSong->m_StopSegments.GetSize(); i++ )
{
if( m_pSong->m_StopSegments[i].m_fStartBeat == m_fBeat )
break;
}
if( i == m_pSong->m_FreezeSegments.GetSize() ) // there is no BPMSegment at the current beat
if( i == m_pSong->m_StopSegments.GetSize() ) // there is no BPMSegment at the current beat
{
// create a new FreezeSegment
// create a new StopSegment
if( fFreezeDelta > 0 )
m_pSong->AddFreezeSegment( FreezeSegment(m_fBeat, fFreezeDelta) );
m_pSong->AddStopSegment( StopSegment(m_fBeat, fFreezeDelta) );
}
else // FreezeSegment being modified is m_FreezeSegments[i]
else // StopSegment being modified is m_StopSegments[i]
{
m_pSong->m_FreezeSegments[i].m_fFreezeSeconds += fFreezeDelta;
if( m_pSong->m_FreezeSegments[i].m_fFreezeSeconds <= 0 )
m_pSong->m_FreezeSegments.RemoveAt( i );
m_pSong->m_StopSegments[i].m_fStopSeconds += fFreezeDelta;
if( m_pSong->m_StopSegments[i].m_fStopSeconds <= 0 )
m_pSong->m_StopSegments.RemoveAt( i );
}
}
break;
@@ -729,12 +734,15 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
float fOffsetDelta;
switch( DeviceI.button )
{
case DIK_F11: fOffsetDelta = -0.025f; break;
case DIK_F12: fOffsetDelta = +0.025f; break;
case DIK_F11: fOffsetDelta = -0.020f; break;
case DIK_F12: fOffsetDelta = +0.020f; break;
default: ASSERT(0);
}
if( type == IET_FAST_REPEAT )
fOffsetDelta *= 40;
switch( type )
{
case IET_SLOW_REPEAT: fOffsetDelta *= 10; break;
case IET_FAST_REPEAT: fOffsetDelta *= 40; break;
}
m_pSong->m_fBeat0OffsetInSeconds += fOffsetDelta;
}
@@ -753,8 +761,11 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
case DIK_F2: fOffsetDelta = +0.025f; break;
default: ASSERT(0);
}
if( type == IET_FAST_REPEAT )
fOffsetDelta *= 40;
switch( type )
{
case IET_SLOW_REPEAT: fOffsetDelta *= 10; break;
case IET_FAST_REPEAT: fOffsetDelta *= 40; break;
}
m_pSong->m_fMusicSampleStartSeconds += fOffsetDelta;
}
@@ -769,8 +780,11 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
case DIK_ADD: fDelta = +0.025f; break;
default: ASSERT(0);
}
if( type == IET_FAST_REPEAT )
fDelta *= 40;
switch( type )
{
case IET_SLOW_REPEAT: fDelta *= 10; break;
case IET_FAST_REPEAT: fDelta *= 40; break;
}
m_pSong->m_fMusicSampleLengthSeconds += fDelta;
}
@@ -849,10 +863,15 @@ void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType typ
}
}
float fSongBeat, fBPS;
bool bFreeze;
m_pSong->GetBeatAndBPSFromElapsedTime( m_soundMusic.GetPositionSeconds(), fSongBeat, fBPS, bFreeze );
const float fMaxBeatDifference = fBPS * PREFSMAN->m_fJudgeWindow / PREFSMAN->m_SongOptions.m_fMusicRate;
switch( StyleI.player )
{
case PLAYER_1:
m_Player.HandlePlayerStep( m_fBeat, StyleI.col, 0.35f );
m_Player.HandlePlayerStep( m_fBeat, StyleI.col, fMaxBeatDifference );
return;
}
+2 -1
View File
@@ -112,7 +112,8 @@ ScreenEditMenu::ScreenEditMenu()
m_Menu.Load(
THEME->GetPathTo(GRAPHIC_EDIT_BACKGROUND),
THEME->GetPathTo(GRAPHIC_EDIT_TOP_EDGE),
ssprintf("%s %s change music START to continue", CString(char(1)), CString(char(2)) )
ssprintf("%s %s change music START to continue", CString(char(1)), CString(char(2)) ),
false, true, 40
);
this->AddActor( &m_Menu );
+2 -1
View File
@@ -164,7 +164,8 @@ ScreenEvaluation::ScreenEvaluation( bool bSummary )
m_Menu.Load(
THEME->GetPathTo(GRAPHIC_EVALUATION_BACKGROUND),
m_ResultMode==RM_ARCADE_SUMMARY ? THEME->GetPathTo(GRAPHIC_EVALUATION_SUMMARY_TOP_EDGE) : THEME->GetPathTo(GRAPHIC_EVALUATION_TOP_EDGE),
"Press START to continue."
"Press START to continue.",
false, true, 40
);
this->AddActor( &m_Menu );
+2 -1
View File
@@ -91,7 +91,8 @@ ScreenEz2SelectPlayer::ScreenEz2SelectPlayer()
m_Menu.Load(
THEME->GetPathTo(GRAPHIC_SELECT_STYLE_BACKGROUND),
THEME->GetPathTo(GRAPHIC_SELECT_STYLE_TOP_EDGE),
ssprintf("Use %c to select your pad", char(4) )
ssprintf("Use %c %c to select, then press START", char(1), char(2) ),
false, true, 40
);
this->AddActor( &m_Menu );
+2 -1
View File
@@ -173,7 +173,8 @@ ScreenEz2SelectStyle::ScreenEz2SelectStyle()
m_Menu.Load(
THEME->GetPathTo(GRAPHIC_SELECT_STYLE_BACKGROUND),
THEME->GetPathTo(GRAPHIC_SELECT_STYLE_TOP_EDGE),
ssprintf("Use %c %c to select, then press START", char(1), char(2) )
ssprintf("Use %c %c to select, then press START", char(1), char(2) ),
false, true, 40
);
this->AddActor( &m_Menu );
+134 -43
View File
@@ -50,7 +50,7 @@ const float TIME_BETWEEN_DANCING_COMMENTS = 15;
// received while STATE_DANCING
const ScreenMessage SM_SongEnded = ScreenMessage(SM_User+102);
const ScreenMessage SM_NotesEnded = ScreenMessage(SM_User+102);
const ScreenMessage SM_LifeIs0 = ScreenMessage(SM_User+103);
@@ -91,10 +91,10 @@ ScreenGameplay::ScreenGameplay()
Song* pSong = pCourse->m_apSongs[i];
DifficultyClass dc = pCourse->m_aDifficultyClasses[i];
for( int j=0; j<pSong->m_arrayNotes.GetSize(); j++ )
for( int j=0; j<pSong->m_apNotes.GetSize(); j++ )
{
Notes* pNotes = pSong->m_arrayNotes[j];
if( pSong->m_arrayNotes[j]->m_DifficultyClass == dc )
Notes* pNotes = pSong->m_apNotes[j];
if( pSong->m_apNotes[j]->m_DifficultyClass == dc )
{
m_apSongQueue.Add( pSong );
for( int p=0; p<NUM_PLAYERS; p++ )
@@ -252,10 +252,28 @@ ScreenGameplay::ScreenGameplay()
m_soundFail.Load( THEME->GetPathTo(SOUND_GAMEPLAY_FAILED) );
m_announcerReady.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_READY) );
m_announcerHereWeGo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_HERE_WE_GO_NORMAL) );
if( PREFSMAN->IsExtraStage() || PREFSMAN->IsExtraStage2() )
m_announcerHereWeGo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_HERE_WE_GO_EXTRA) );
else if( PREFSMAN->IsFinalStage() )
m_announcerHereWeGo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_HERE_WE_GO_FINAL) );
else
m_announcerHereWeGo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_HERE_WE_GO_NORMAL) );
m_announcerDanger.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_COMMENT_DANGER) );
m_announcerGood.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_COMMENT_GOOD) );
m_announcerHot.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_COMMENT_HOT) );
m_announcer100Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_100_COMBO) );
m_announcer200Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_200_COMBO) );
m_announcer300Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_300_COMBO) );
m_announcer400Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_400_COMBO) );
m_announcer500Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_500_COMBO) );
m_announcer600Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_600_COMBO) );
m_announcer700Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_700_COMBO) );
m_announcer800Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_800_COMBO) );
m_announcer900Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_900_COMBO) );
m_announcer1000Combo.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_1000_COMBO) );
m_announcerComboStopped.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_COMBO_STOPPED) );
m_announcerCleared.Load( ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_CLEARED) );
m_announcerFailComment.Load(ANNOUNCER->GetPathTo(ANNOUNCER_GAMEPLAY_FAILED) );
@@ -342,7 +360,9 @@ void ScreenGameplay::LoadNextSong()
);
}
m_soundMusic.Load( m_pCurSong->GetMusicPath() );
m_soundMusic.Load( m_pCurSong->GetMusicPath(), true ); // enable accurate sync
float fStartSeconds = min( 0, m_pCurSong->GetElapsedTimeFromBeat(m_pCurSong->m_fFirstBeat-4) );
m_soundMusic.SetPositionSeconds( fStartSeconds );
m_soundMusic.SetPlaybackRate( PREFSMAN->m_SongOptions.m_fMusicRate );
m_Background.LoadFromSong( m_pCurSong );
@@ -357,6 +377,7 @@ void ScreenGameplay::Update( float fDeltaTime )
//LOG->WriteLine( "ScreenGameplay::Update(%f)", fDeltaTime );
Screen::Update( fDeltaTime );
m_soundMusic.Update( fDeltaTime );
if( m_pCurSong == NULL )
return;
@@ -368,7 +389,7 @@ void ScreenGameplay::Update( float fDeltaTime )
m_pCurSong->GetBeatAndBPSFromElapsedTime( fPositionSeconds, fSongBeat, fBPS, bFreeze );
m_Background.SetSongBeat( fSongBeat, bFreeze );
m_Background.SetSongBeat( fSongBeat, bFreeze, fPositionSeconds );
//LOG->WriteLine( "m_fOffsetInBeats = %f, m_fBeatsPerSecond = %f, m_Music.GetPositionSeconds = %f", m_fOffsetInBeats, m_fBeatsPerSecond, m_Music.GetPositionSeconds() );
@@ -427,35 +448,31 @@ void ScreenGameplay::Update( float fDeltaTime )
case STATE_DANCING:
// Check for end of song
if( m_DancingState == STATE_DANCING &&
m_soundMusic.GetLengthSeconds() - m_soundMusic.GetPositionSeconds() < 2 )
this->SendScreenMessage( SM_SongEnded, 1 );
if( fSongBeat > m_pCurSong->m_fLastBeat+4 )
this->SendScreenMessage( SM_NotesEnded, 0 );
// Check to see if it's time to play a gameplay comment
if( PREFSMAN->m_bAnnouncer )
m_fTimeLeftBeforeDancingComment -= fDeltaTime;
if( m_fTimeLeftBeforeDancingComment <= 0 )
{
m_fTimeLeftBeforeDancingComment -= fDeltaTime;
if( m_fTimeLeftBeforeDancingComment <= 0 )
{
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; // reset for the next comment
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS; // reset for the next comment
bool bAllInDanger = true;
for( int p=0; p<NUM_PLAYERS; p++ )
if( !m_LifeMeter[p].IsInDanger() )
bAllInDanger = false;
bool bAllInDanger = true;
for( int p=0; p<NUM_PLAYERS; p++ )
if( !m_LifeMeter[p].IsInDanger() )
bAllInDanger = false;
bool bOneIsHot = false;
for( p=0; p<NUM_PLAYERS; p++ )
if( m_LifeMeter[p].IsHot() )
bOneIsHot = true;
bool bOneIsHot = false;
for( p=0; p<NUM_PLAYERS; p++ )
if( m_LifeMeter[p].IsHot() )
bOneIsHot = true;
if( bOneIsHot )
m_announcerHot.PlayRandom();
else if( bAllInDanger )
m_announcerDanger.PlayRandom();
else
m_announcerGood.PlayRandom();
}
if( bOneIsHot )
m_announcerHot.PlayRandom();
else if( bAllInDanger )
m_announcerDanger.PlayRandom();
else
m_announcerGood.PlayRandom();
}
}
@@ -620,8 +637,7 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
break;
case SM_User+2:
m_sprReady.StartFocusing();
if( PREFSMAN->m_bAnnouncer )
m_announcerReady.PlayRandom();
m_announcerReady.PlayRandom();
break;
case SM_User+3:
break;
@@ -630,9 +646,8 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
break;
case SM_User+5:
m_sprHereWeGo.StartFocusing();
if( PREFSMAN->m_bAnnouncer )
m_announcerHereWeGo.PlayRandom();
m_Background.SetDiffuseColor( D3DXCOLOR(0.8f,0.8f,0.8f,1) );
m_announcerHereWeGo.PlayRandom();
m_Background.FadeIn();
m_soundMusic.Play();
m_soundMusic.SetPlaybackRate( PREFSMAN->m_SongOptions.m_fMusicRate );
break;
@@ -653,7 +668,7 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
this->SendScreenMessage( SM_BeginFailed, 0 );
m_DancingState = STATE_OUTRO;
break;
case SM_SongEnded:
case SM_NotesEnded:
if( m_DancingState == STATE_OUTRO ) // gameplay already ended
return; // ignore
@@ -664,13 +679,91 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
else // cleared
{
m_StarWipe.CloseWipingRight( SM_ShowCleared );
if( PREFSMAN->m_bAnnouncer )
m_announcerCleared.PlayRandom(); // crowd cheer
m_announcerCleared.PlayRandom(); // crowd cheer
}
m_DancingState = STATE_OUTRO;
break;
// received while STATE_OUTRO
case SM_100Combo:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcer100Combo.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
case SM_200Combo:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcer200Combo.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
case SM_300Combo:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcer300Combo.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
case SM_400Combo:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcer400Combo.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
case SM_500Combo:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcer500Combo.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
case SM_600Combo:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcer600Combo.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
case SM_700Combo:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcer700Combo.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
case SM_800Combo:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcer800Combo.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
case SM_900Combo:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcer900Combo.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
case SM_1000Combo:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcer1000Combo.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
case SM_ComboStopped:
if( m_fTimeLeftBeforeDancingComment < 12 )
{
m_announcerComboStopped.PlayRandom();
m_fTimeLeftBeforeDancingComment = TIME_BETWEEN_DANCING_COMMENTS;
}
break;
// received while STATE_OUTRO
case SM_ShowCleared:
m_sprCleared.StartFocusing();
SCREENMAN->SendMessageToTopScreen( SM_HideCleared, 2.5 );
@@ -692,8 +785,7 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
this->SendScreenMessage( SM_ShowFailed, 0.2f );
break;
case SM_ShowFailed:
if( PREFSMAN->m_bAnnouncer )
m_soundFail.PlayRandom();
m_soundFail.PlayRandom();
// make the background invisible so we don't waste mem bandwidth drawing it
m_Background.BeginTweening( 1 );
@@ -714,8 +806,7 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM )
SCREENMAN->SendMessageToTopScreen( SM_HideFailed, 3.0f );
break;
case SM_PlayFailComment:
if( PREFSMAN->m_bAnnouncer )
m_announcerFailComment.PlayRandom();
m_announcerFailComment.PlayRandom();
break;
case SM_HideFailed:
m_sprFailed.StopTweening();
+25
View File
@@ -26,6 +26,20 @@
#include "DifficultyBanner.h"
// messages sent by Combo
const ScreenMessage SM_100Combo = ScreenMessage(SM_User+200);
const ScreenMessage SM_200Combo = ScreenMessage(SM_User+201);
const ScreenMessage SM_300Combo = ScreenMessage(SM_User+202);
const ScreenMessage SM_400Combo = ScreenMessage(SM_User+203);
const ScreenMessage SM_500Combo = ScreenMessage(SM_User+204);
const ScreenMessage SM_600Combo = ScreenMessage(SM_User+205);
const ScreenMessage SM_700Combo = ScreenMessage(SM_User+206);
const ScreenMessage SM_800Combo = ScreenMessage(SM_User+207);
const ScreenMessage SM_900Combo = ScreenMessage(SM_User+208);
const ScreenMessage SM_1000Combo = ScreenMessage(SM_User+209);
const ScreenMessage SM_ComboStopped = ScreenMessage(SM_User+210);
class ScreenGameplay : public Screen
{
public:
@@ -95,6 +109,17 @@ private:
RandomSample m_announcerDanger;
RandomSample m_announcerGood;
RandomSample m_announcerHot;
RandomSample m_announcer100Combo;
RandomSample m_announcer200Combo;
RandomSample m_announcer300Combo;
RandomSample m_announcer400Combo;
RandomSample m_announcer500Combo;
RandomSample m_announcer600Combo;
RandomSample m_announcer700Combo;
RandomSample m_announcer800Combo;
RandomSample m_announcer900Combo;
RandomSample m_announcer1000Combo;
RandomSample m_announcerComboStopped;
RandomStream m_announcerCleared;
RandomStream m_announcerFailComment;
RandomStream m_announcerGameOver;
+6 -5
View File
@@ -42,8 +42,8 @@ const CString CREDIT_LINES[] =
"",
"GRAPHICS:",
"TofuBoy (Lucas Tang)",
"DJ McFox (Ryan McKanna)",
"SPiGuMuS",
"DJ McFox (Ryan McKanna)",
"",
"",
"",
@@ -53,7 +53,7 @@ const CString CREDIT_LINES[] =
"",
"",
"SOUND:",
"Kyle 'Keel' Ward",
"Kyle 'KeeL' Ward",
"",
"",
"",
@@ -80,10 +80,11 @@ const CString CREDIT_LINES[] =
"",
"",
"SPECIAL THANKS TO:",
"SimWolf",
"Dance With Intensity",
"DDR Llama",
"DDRLlama",
"DDRManiaX",
"SimWolf",
"DJ DraftHorse",
"Dance With Intensity",
"Lagged",
"The Melting Pot",
"DDRJamz Global BBS",
+5 -2
View File
@@ -50,7 +50,8 @@ ScreenOptions::ScreenOptions( CString sBackgroundPath, CString sTopEdgePath )
m_Menu.Load(
sBackgroundPath,
sTopEdgePath,
ssprintf("%s %s to change line %s %s to select between options then press START", CString(char(3)), CString(char(4)), CString(char(1)), CString(char(2)) )
ssprintf("%s %s to change line %s %s to select between options then press START", CString(char(3)), CString(char(4)), CString(char(1)), CString(char(2)) ),
false, true, 40
);
this->AddActor( &m_Menu );
m_Menu.TweenOnScreenFromBlack( SM_None );
@@ -132,12 +133,14 @@ void ScreenOptions::GetWidthXY( PlayerNumber p, int iRow, float &fWidthOut, floa
void ScreenOptions::InitOptionsText()
{
const float fLineGap = LINE_GAP_Y - max(0, (m_iNumOptionLines-10)*2);
// init m_textOptions from optionLines
for( int i=0; i<m_iNumOptionLines; i++ ) // foreach options line
{
OptionLineData &optline = m_OptionLineData[i];
float fY = LINE_START_Y + LINE_GAP_Y*i;
float fY = LINE_START_Y + fLineGap*i;
BitmapText &title = m_textOptionLineTitles[i];
+1 -24
View File
@@ -35,7 +35,6 @@ enum {
PO_HOLD_NOTES,
PO_DARK,
PO_DRAIN,
PO_SKIN,
NUM_PLAYER_OPTIONS_LINES
};
OptionLineData g_PlayerOptionsLines[NUM_PLAYER_OPTIONS_LINES] = {
@@ -49,7 +48,6 @@ OptionLineData g_PlayerOptionsLines[NUM_PLAYER_OPTIONS_LINES] = {
{ "Holds", 2, {"OFF","ON"} },
{ "Dark", 2, {"OFF","ON"} },
{ "Drain", 3, {"NORMAL", "NO-RECOVER", "SUDDEN-DEATH"} },
{ "Skin", 0, {""} }, // fill this in on ImportOptions();
};
@@ -72,16 +70,6 @@ ScreenPlayerOptions::ScreenPlayerOptions() :
void ScreenPlayerOptions::ImportOptions()
{
// fill in skin names
CStringArray arraySkinNames;
GAMEMAN->GetSkinNames( arraySkinNames );
m_OptionLineData[PO_SKIN].iNumOptions = arraySkinNames.GetSize();
for( int i=0; i<arraySkinNames.GetSize(); i++ )
strcpy( m_OptionLineData[PO_SKIN].szOptionsText[i], arraySkinNames[i] );
for( int p=0; p<NUM_PLAYERS; p++ )
{
PlayerOptions &po = PREFSMAN->m_PlayerOptions[p];
@@ -103,14 +91,6 @@ void ScreenPlayerOptions::ImportOptions()
m_iSelectedOption[p][PO_HOLD_NOTES] = po.m_bHoldNotes ? 1 : 0;
m_iSelectedOption[p][PO_DARK] = po.m_bDark ? 1 : 0;
m_iSelectedOption[p][PO_DRAIN] = po.m_DrainType;
// highlight currently selected skin
for( int s=0; i<m_OptionLineData[PO_SKIN].iNumOptions; s++ ) // foreach skin
if( m_OptionLineData[PO_SKIN].szOptionsText[s] == GAMEMAN->m_sCurrentSkin[p] )
{
m_iSelectedOption[p][PO_SKIN] = s;
break;
}
}
}
@@ -139,10 +119,7 @@ void ScreenPlayerOptions::ExportOptions()
po.m_ColorType = (PlayerOptions::ColorType)m_iSelectedOption[p][PO_COLOR];
po.m_bHoldNotes = (m_iSelectedOption[p][PO_HOLD_NOTES] == 1);
po.m_bDark = (m_iSelectedOption[p][PO_DARK] == 1);
po.m_DrainType = (PlayerOptions::DrainType)m_iSelectedOption[p][PO_DRAIN];
int iSelectedSkin = m_iSelectedOption[p][PO_SKIN];
GAMEMAN->m_sCurrentSkin[p] = m_OptionLineData[PO_SKIN].szOptionsText[iSelectedSkin];
po.m_DrainType = (PlayerOptions::DrainType)m_iSelectedOption[p][PO_DRAIN];
}
}
+8 -1
View File
@@ -22,7 +22,12 @@
ScreenSandbox::ScreenSandbox()
{
m_sound.Load( THEME->GetPathTo(SOUND_MENU_START) );
m_text.Load( THEME->GetPathTo(FONT_NORMAL) );
m_text.SetXY( CENTER_X, CENTER_Y );
this->AddActor( &m_text );
m_sound.Load( THEME->GetPathTo(SOUND_MENU_MUSIC) );
m_sound.SetPositionSeconds( -10 );
m_sound.Play();
//this->AddActor( &m_spr );
@@ -32,6 +37,8 @@ ScreenSandbox::ScreenSandbox()
void ScreenSandbox::Update( float fDeltaTime )
{
Screen::Update( fDeltaTime );
m_sound.Update( fDeltaTime );
m_text.SetText( ssprintf("%f", m_sound.GetPositionSeconds()) );
}
void ScreenSandbox::DrawPrimitives()
+3 -9
View File
@@ -1,3 +1,4 @@
#pragma once
/*
-----------------------------------------------------------------------------
File: ScreenSandbox.h
@@ -8,10 +9,6 @@
-----------------------------------------------------------------------------
*/
#ifndef _ScreenSandbox_H_
#define _ScreenSandbox_H_
#include "Screen.h"
#include "Sprite.h"
#include "BitmapText.h"
@@ -30,10 +27,7 @@ public:
virtual void Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI );
virtual void HandleScreenMessage( const ScreenMessage SM );
Sprite m_spr;
RageSoundSample m_sound;
BitmapText m_text;
RageSoundStream m_sound;
};
#endif
+3 -2
View File
@@ -61,8 +61,9 @@ ScreenSelectCourse::ScreenSelectCourse()
THEME->GetPathTo(GRAPHIC_SELECT_COURSE_BACKGROUND),
THEME->GetPathTo(GRAPHIC_SELECT_COURSE_TOP_EDGE),
ssprintf("%c or %c change course then press START",
char(1), char(2), char(3), char(3), char(4), char(4), char(3), char(4), char(3), char(4) )
);
char(1), char(2), char(3), char(3), char(4), char(4), char(3), char(4), char(3), char(4) ),
false, true, 60
);
this->AddActor( &m_Menu );
m_CourseInfoFrame.SetXY( COURSE_INFO_FRAME_X, COURSE_INFO_FRAME_Y );
+2 -1
View File
@@ -81,7 +81,8 @@ ScreenSelectDifficulty::ScreenSelectDifficulty()
m_Menu.Load(
THEME->GetPathTo(GRAPHIC_SELECT_DIFFICULTY_BACKGROUND) ,
THEME->GetPathTo(GRAPHIC_SELECT_DIFFICULTY_TOP_EDGE),
ssprintf("Use %c %c to select, then press START", char(1), char(2))
ssprintf("Use %c %c to select, then press START", char(1), char(2)),
false, true, 40
);
this->AddActor( &m_Menu );
+2 -3
View File
@@ -60,7 +60,8 @@ ScreenSelectGroup::ScreenSelectGroup()
m_Menu.Load(
THEME->GetPathTo(GRAPHIC_SELECT_GROUP_BACKGROUND) ,
THEME->GetPathTo(GRAPHIC_SELECT_GROUP_TOP_EDGE),
ssprintf("Use %c %c to select, then press START", char(1), char(2))
ssprintf("Use %c %c to select, then press START", char(1), char(2)),
false, true, 40
);
this->AddActor( &m_Menu );
@@ -101,8 +102,6 @@ ScreenSelectGroup::ScreenSelectGroup()
m_textGroup[i].SetXY( BUTTON_X, BUTTON_START_Y + BUTTON_GAP_Y*i );
m_textGroup[i].SetText( SONGMAN->ShortenGroupName( sGroupName ) );
m_textGroup[i].SetZoom( 0.8f );
if( m_textGroup[i].GetWidestLineWidthInSourcePixels()*0.8f > m_sprGroupButton[i].GetUnzoomedWidth() )
m_textGroup[i].SetZoomX( m_textGroup[i].GetWidestLineWidthInSourcePixels()*0.8f / (float)m_sprGroupButton[i].GetUnzoomedWidth() );
m_textGroup[i].SetShadowLength( 2 );
if( i == 0 ) m_textGroup[i].TurnRainbowOn();
+3 -2
View File
@@ -74,8 +74,9 @@ ScreenSelectMusic::ScreenSelectMusic()
THEME->GetPathTo(GRAPHIC_SELECT_MUSIC_BACKGROUND),
THEME->GetPathTo(GRAPHIC_SELECT_MUSIC_TOP_EDGE),
ssprintf("%c or %c change music %c%c easier difficulty %c%c harder difficulty %c%c%c%c change sort",
char(1), char(2), char(3), char(3), char(4), char(4), char(3), char(4), char(3), char(4) )
);
char(1), char(2), char(3), char(3), char(4), char(4), char(3), char(4), char(3), char(4) ),
false, true, 60
);
this->AddActor( &m_Menu );
m_SongInfoFrame.SetXY( SONG_INFO_FRAME_X, SONG_INFO_FRAME_Y );
+2 -1
View File
@@ -99,7 +99,8 @@ ScreenSelectStyle::ScreenSelectStyle()
m_Menu.Load(
THEME->GetPathTo(GRAPHIC_SELECT_STYLE_BACKGROUND),
THEME->GetPathTo(GRAPHIC_SELECT_STYLE_TOP_EDGE),
ssprintf("Use %c %c to select, then press START", char(1), char(2) )
ssprintf("Use %c %c to select, then press START", char(1), char(2) ),
false, true, 40
);
this->AddActor( &m_Menu );
+9 -2
View File
@@ -26,11 +26,14 @@
#include "AnnouncerManager.h"
const ScreenMessage SM_StartFadingOut = ScreenMessage(SM_User + 1);
const ScreenMessage SM_DoneFadingIn = ScreenMessage(SM_User + 2);
const ScreenMessage SM_GoToNextState = ScreenMessage(SM_User + 3);
ScreenStage::ScreenStage()
{
m_pNextScreen = NULL;
m_textStage.Load( THEME->GetPathTo(FONT_STAGE) );
m_textStage.TurnShadowOff();
@@ -79,7 +82,8 @@ ScreenStage::ScreenStage()
m_textStage.SetTweenDiffuseColor( D3DXCOLOR(1,1,1,1) );
this->AddActor( &m_textStage );
this->SendScreenMessage( SM_StartFadingOut, 3 );
this->SendScreenMessage( SM_DoneFadingIn, 0.6f );
this->SendScreenMessage( SM_StartFadingOut, 1.2f );
}
@@ -92,8 +96,11 @@ void ScreenStage::HandleScreenMessage( const ScreenMessage SM )
m_textStage.SetTweenDiffuseColor( D3DXCOLOR(1,1,1,0) );
this->SendScreenMessage( SM_GoToNextState, 0.8f );
break;
case SM_DoneFadingIn:
m_pNextScreen = new ScreenGameplay;
break;
case SM_GoToNextState:
SCREENMAN->SetNewScreen( new ScreenGameplay );
SCREENMAN->SetNewScreen( m_pNextScreen );
break;
}
}
+1
View File
@@ -24,6 +24,7 @@ private:
bool m_bTryExtraStage;
BitmapText m_textStage;
Screen* m_pNextScreen;
};
+19 -9
View File
@@ -23,6 +23,7 @@
#include "ScreenEditMenu.h"
#include "ScreenSelectStyle.h"
#include "ScreenSelectGame.h"
#include "ScreenAppearanceOptions.h"
#include "RageLog.h"
#include "SongManager.h"
#include "AnnouncerManager.h"
@@ -40,12 +41,13 @@ const CString CHOICE_TEXT[ScreenTitleMenu::NUM_TITLE_MENU_CHOICES] = {
"SWITCH GAME",
"CONFIG KEY/JOY",
"GAME OPTIONS",
"APPEARANCE OPTIONS",
"EDIT/RECORD/SYNCH",
"EXIT",
};
const float CHOICES_START_Y = 66;
const float CHOICES_GAP_Y = 56;
const float CHOICES_START_Y = 62;
const float CHOICES_GAP_Y = 52;
const float HELP_X = CENTER_X;
const float HELP_Y = SCREEN_HEIGHT-55;
@@ -57,6 +59,7 @@ const ScreenMessage SM_GoToSelectStyle = ScreenMessage(SM_User+3);
const ScreenMessage SM_GoToSelectGame = ScreenMessage(SM_User+4);
const ScreenMessage SM_GoToMapInstruments = ScreenMessage(SM_User+5);
const ScreenMessage SM_GoToGameOptions = ScreenMessage(SM_User+6);
const ScreenMessage SM_GoToAppearanceOptions= ScreenMessage(SM_User+7);
const ScreenMessage SM_GoToEdit = ScreenMessage(SM_User+10);
const ScreenMessage SM_DoneOpening = ScreenMessage(SM_User+11);
const ScreenMessage SM_GoToEz2 = ScreenMessage(SM_User+12);
@@ -101,7 +104,7 @@ ScreenTitleMenu::ScreenTitleMenu()
m_textVersion.Load( THEME->GetPathTo(FONT_NORMAL) );
m_textVersion.SetHorizAlign( Actor::align_right );
m_textVersion.SetText( "v3.0 beta 1" );
m_textVersion.SetText( "v3.0 beta 4" );
m_textVersion.SetDiffuseColor( D3DXCOLOR(0.6f,0.6f,0.6f,1) ); // light gray
m_textVersion.SetXY( SCREEN_RIGHT-16, SCREEN_BOTTOM-20 );
m_textVersion.SetZoom( 0.5f );
@@ -146,12 +149,14 @@ ScreenTitleMenu::ScreenTitleMenu()
SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_TITLE_MENU_GAME_NAME) );
m_soundAttract.Load( ANNOUNCER->GetPathTo(ANNOUNCER_TITLE_MENU_ATTRACT) );
m_soundChange.Load( THEME->GetPathTo(SOUND_TITLE_MENU_CHANGE) );
m_soundSelect.Load( THEME->GetPathTo(SOUND_MENU_START) );
m_soundInvalid.Load( THEME->GetPathTo(SOUND_MENU_INVALID) );
for( i=0; i<3000; i++ )
this->SendScreenMessage( SM_PlayAttract, (float)15+i*15 );
this->SendScreenMessage( SM_PlayAttract, (float)20+i*20 );
m_TitleMenuChoice = CHOICE_GAME_START;
@@ -184,13 +189,9 @@ void ScreenTitleMenu::HandleScreenMessage( const ScreenMessage SM )
switch( SM )
{
case SM_DoneOpening:
if( PREFSMAN->m_bAnnouncer )
{
m_soundTitle.PlayRandom();
}
break;
case SM_PlayAttract:
SOUND->PlayOnceStreamedFromDir( ANNOUNCER->GetPathTo(ANNOUNCER_TITLE_MENU_ATTRACT) );
m_soundAttract.PlayRandom();
break;
case SM_GoToCaution:
SCREENMAN->SetNewScreen( new ScreenCaution );
@@ -207,6 +208,9 @@ void ScreenTitleMenu::HandleScreenMessage( const ScreenMessage SM )
case SM_GoToGameOptions:
SCREENMAN->SetNewScreen( new ScreenGameOptions );
break;
case SM_GoToAppearanceOptions:
SCREENMAN->SetNewScreen( new ScreenAppearanceOptions );
break;
case SM_GoToEdit:
SCREENMAN->SetNewScreen( new ScreenEditMenu );
break;
@@ -294,6 +298,10 @@ void ScreenTitleMenu::MenuStart( const PlayerNumber p )
m_soundSelect.PlayRandom();
m_Fade.CloseWipingRight( SM_GoToGameOptions );
return;
case CHOICE_APPEARANCE_OPTIONS:
m_soundSelect.PlayRandom();
m_Fade.CloseWipingRight( SM_GoToAppearanceOptions );
return;
case CHOICE_EDIT:
if( SONGMAN->m_pSongs.GetSize() == 0 )
{
@@ -322,6 +330,8 @@ void ScreenTitleMenu::MenuStart( const PlayerNumber p )
m_soundSelect.PlayRandom();
PostQuitMessage(0);
return;
default:
ASSERT(0);
}
}
+1 -1
View File
@@ -33,6 +33,7 @@ public:
CHOICE_SELECT_GAME,
CHOICE_MAP_INSTRUMENTS,
CHOICE_GAME_OPTIONS,
CHOICE_APPEARANCE_OPTIONS,
CHOICE_EDIT,
CHOICE_EXIT,
NUM_TITLE_MENU_CHOICES // leave this at the end!
@@ -57,7 +58,6 @@ private:
TransitionFade m_Fade;
RandomStream m_soundTitle;
RandomStream m_soundAttract;
RandomSample m_soundChange;
RandomSample m_soundSelect;
+278 -168
View File
@@ -19,7 +19,7 @@
#include "NoteData.h"
const int FILE_CACHE_VERSION = 29; // increment this to force a cache reload (useful when the SM file format changes)
const int FILE_CACHE_VERSION = 43; // increment this to force a cache reload (useful when the SM file format changes)
int CompareBPMSegments(const void *arg1, const void *arg2)
@@ -44,11 +44,11 @@ void SortBPMSegmentsArray( CArray<BPMSegment,BPMSegment&> &arrayBPMSegments )
qsort( arrayBPMSegments.GetData(), arrayBPMSegments.GetSize(), sizeof(BPMSegment), CompareBPMSegments );
}
int CompareFreezeSegments(const void *arg1, const void *arg2)
int CompareStopSegments(const void *arg1, const void *arg2)
{
// arg1 and arg2 are of type Step**
FreezeSegment* seg1 = (FreezeSegment*)arg1;
FreezeSegment* seg2 = (FreezeSegment*)arg2;
StopSegment* seg1 = (StopSegment*)arg1;
StopSegment* seg2 = (StopSegment*)arg2;
float score1 = seg1->m_fStartBeat;
float score2 = seg2->m_fStartBeat;
@@ -61,9 +61,31 @@ int CompareFreezeSegments(const void *arg1, const void *arg2)
return 1;
}
void SortFreezeSegmentsArray( CArray<FreezeSegment,FreezeSegment&> &arrayFreezeSegments )
void SortStopSegmentsArray( CArray<StopSegment,StopSegment&> &arrayStopSegments )
{
qsort( arrayFreezeSegments.GetData(), arrayFreezeSegments.GetSize(), sizeof(FreezeSegment), CompareFreezeSegments );
qsort( arrayStopSegments.GetData(), arrayStopSegments.GetSize(), sizeof(StopSegment), CompareStopSegments );
}
int CompareAnimationSegments(const void *arg1, const void *arg2)
{
// arg1 and arg2 are of type Step**
AnimationSegment* seg1 = (AnimationSegment*)arg1;
AnimationSegment* seg2 = (AnimationSegment*)arg2;
float score1 = seg1->m_fStartBeat;
float score2 = seg2->m_fStartBeat;
if( score1 == score2 )
return 0;
else if( score1 < score2 )
return -1;
else
return 1;
}
void SortAnimationSegmentsArray( CArray<AnimationSegment,AnimationSegment&> &arrayAnimationSegments )
{
qsort( arrayAnimationSegments.GetData(), arrayAnimationSegments.GetSize(), sizeof(AnimationSegment), CompareAnimationSegments );
}
@@ -78,14 +100,16 @@ Song::Song()
m_fMusicSampleLengthSeconds = 16; // start fading out at m_fMusicSampleLengthSeconds-1 seconds
m_iMusicBytes = 0;
m_fMusicLengthSeconds = 0;
m_fFirstBeat = -1;
m_fLastBeat = -1;
}
Song::~Song()
{
for( int i=0; i<m_arrayNotes.GetSize(); i++ )
SAFE_DELETE( m_arrayNotes[i] );
for( int i=0; i<m_apNotes.GetSize(); i++ )
SAFE_DELETE( m_apNotes[i] );
m_arrayNotes.RemoveAll();
m_apNotes.RemoveAll();
}
@@ -96,10 +120,17 @@ void Song::AddBPMSegment( BPMSegment seg )
}
void Song::AddFreezeSegment( FreezeSegment seg )
void Song::AddStopSegment( StopSegment seg )
{
m_FreezeSegments.Add( seg );
SortFreezeSegmentsArray( m_FreezeSegments );
m_StopSegments.Add( seg );
SortStopSegmentsArray( m_StopSegments );
}
void Song::AddAnimationSegment( AnimationSegment seg )
{
m_AnimationSegments.Add( seg );
SortAnimationSegmentsArray( m_AnimationSegments );
}
@@ -124,12 +155,12 @@ void Song::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, fl
// calculate the number of seconds in this segment
float fSecondsInThisSegment = fBeatsInThisSegment / fBPS;
for( int j=0; j<m_FreezeSegments.GetSize(); j++ ) // foreach freeze
for( int j=0; j<m_StopSegments.GetSize(); j++ ) // foreach freeze
{
if( fStartBeatThisSegment <= m_FreezeSegments[j].m_fStartBeat && m_FreezeSegments[j].m_fStartBeat < fStartBeatNextSegment )
if( fStartBeatThisSegment <= m_StopSegments[j].m_fStartBeat && m_StopSegments[j].m_fStartBeat < fStartBeatNextSegment )
{
// this freeze lies within this BPMSegment
fSecondsInThisSegment += m_FreezeSegments[j].m_fFreezeSeconds;
fSecondsInThisSegment += m_StopSegments[j].m_fStopSeconds;
}
}
@@ -145,20 +176,20 @@ void Song::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, fl
float fBeatEstimate = fStartBeatThisSegment + fElapsedTime*fBPS;
for( int j=0; j<m_FreezeSegments.GetSize(); j++ ) // foreach freeze
for( int j=0; j<m_StopSegments.GetSize(); j++ ) // foreach freeze
{
if( fStartBeatThisSegment <= m_FreezeSegments[j].m_fStartBeat && m_FreezeSegments[j].m_fStartBeat <= fStartBeatNextSegment )
if( fStartBeatThisSegment <= m_StopSegments[j].m_fStartBeat && m_StopSegments[j].m_fStartBeat <= fStartBeatNextSegment )
{
// this freeze lies within this BPMSegment
if( m_FreezeSegments[j].m_fStartBeat <= fBeatEstimate )
if( m_StopSegments[j].m_fStartBeat <= fBeatEstimate )
{
fElapsedTime -= m_FreezeSegments[j].m_fFreezeSeconds;
fElapsedTime -= m_StopSegments[j].m_fStopSeconds;
// re-estimate
fBeatEstimate = fStartBeatThisSegment + fElapsedTime*fBPS;
if( fBeatEstimate < m_FreezeSegments[j].m_fStartBeat )
if( fBeatEstimate < m_StopSegments[j].m_fStartBeat )
{
fBeatOut = m_FreezeSegments[j].m_fStartBeat;
fBeatOut = m_StopSegments[j].m_fStartBeat;
fBPSOut = fBPS;
bFreezeOut = true;
return;
@@ -185,7 +216,7 @@ void Song::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, fl
float Song::GetElapsedTimeFromBeat( float fBeat )
{
float fElapsedTimeBestGuess = 100; // seconds
float fSecondsToMove = fElapsedTimeBestGuess/2; // seconds
float fSecondsToMove = fElapsedTimeBestGuess; // seconds
float fBeatOut, fBPSOut;
bool bFreezeOut;
@@ -203,21 +234,17 @@ float Song::GetElapsedTimeFromBeat( float fBeat )
return fElapsedTimeBestGuess;
}
void Song::GetMainAndSubTitlesFromFullTitle( CString sFullTitle, CString &sMainTitleOut, CString &sSubTitleOut )
void Song::GetMainAndSubTitlesFromFullTitle( const CString sFullTitle, CString &sMainTitleOut, CString &sSubTitleOut )
{
char sLeftSeps[] = { '-', '~', '(', '[' };
char sRightSeps[] = { '-', '~', ')', ']' };
ASSERT( sizeof(sLeftSeps) == sizeof(sRightSeps) );
for( int i=0; i<sizeof(sLeftSeps); i++ )
const CString sLeftSeps[] = { " -", " ~", " (", " [" };
int iNumSeps = sizeof(sLeftSeps)/sizeof(CString);
for( int i=0; i<iNumSeps; i++ )
{
int iBeginIndex = sFullTitle.Find( sLeftSeps[i] );
if( iBeginIndex == -1 )
continue;
int iEndIndex = sFullTitle.Find( sRightSeps[i], iBeginIndex+1 );
if( iEndIndex == -1 )
continue;
sMainTitleOut = sFullTitle.Left( iBeginIndex-1 );
sSubTitleOut = sFullTitle.Mid( iBeginIndex, iEndIndex-iBeginIndex+1 );
sMainTitleOut = sFullTitle.Left( iBeginIndex );
sSubTitleOut = sFullTitle.Mid( iBeginIndex+1, sFullTitle.GetLength()-iBeginIndex+1 );
return;
}
sMainTitleOut = sFullTitle;
@@ -343,7 +370,7 @@ bool Song::LoadFromBMSDir( CString sDir )
{
Notes* pNewNotes = new Notes;
pNewNotes->LoadFromBMSFile( m_sSongDir + arrayBMSFileNames[i] );
m_arrayNotes.Add( pNewNotes );
m_apNotes.Add( pNewNotes );
}
CString sPath = m_sSongDir + arrayBMSFileNames[0];
@@ -525,7 +552,7 @@ bool Song::LoadFromBMSDir( CString sDir )
value_name = line;
}
if( stricmp(value_name, sTagToLookFor) == 0 )
if( 0==stricmp(value_name, sTagToLookFor) == 0 )
{
fBPM = (float)atof( value_data );
break;
@@ -588,7 +615,7 @@ bool Song::LoadFromBMSDir( CString sDir )
value_name = line;
}
if( stricmp(value_name, sTagToLookFor) == 0 )
if( 0==stricmp(value_name, sTagToLookFor) == 0 )
{
// find the BPM at the time of this freeze
float fBPM = -1;
@@ -616,9 +643,9 @@ bool Song::LoadFromBMSDir( CString sDir )
}
else
{
FreezeSegment newSeg( fFreezeStartBeat, fFreezeSecs );
AddFreezeSegment( newSeg );
LOG->WriteLine( "Inserting new Freeze at beat %f, secs %f", newSeg.m_fStartBeat, newSeg.m_fFreezeSeconds );
StopSegment newSeg( fFreezeStartBeat, fFreezeSecs );
AddStopSegment( newSeg );
LOG->WriteLine( "Inserting new Freeze at beat %f, secs %f", newSeg.m_fStartBeat, newSeg.m_fStopSeconds );
}
file.Close();
@@ -681,7 +708,7 @@ bool Song::LoadFromDWIFile( CString sPath )
// split the value string into tokens
CStringArray arrayValueTokens;
split( sValueString, ":", arrayValueTokens );
split( sValueString, ":", arrayValueTokens, false );
for( int j=0; j<arrayValueTokens.GetSize(); j++ )
{
arrayValueTokens[j].TrimLeft();
@@ -693,16 +720,19 @@ bool Song::LoadFromDWIFile( CString sPath )
CString sValueName = arrayValueTokens.GetAt( 0 );
// handle the data
if( sValueName == "#FILE" )
if( 0==stricmp(sValueName,"#FILE") )
m_sMusicFile = arrayValueTokens[1];
else if( sValueName == "#TITLE" )
else if( 0==stricmp(sValueName,"#TITLE") )
GetMainAndSubTitlesFromFullTitle( arrayValueTokens[1], m_sMainTitle, m_sSubTitle );
else if( sValueName == "#ARTIST" )
else if( 0==stricmp(sValueName,"#ARTIST") )
m_sArtist = arrayValueTokens[1];
else if( sValueName == "#BPM" )
else if( 0==stricmp(sValueName,"#CDTITLE") )
m_sCDTitleFile = arrayValueTokens[1];
else if( 0==stricmp(sValueName,"#BPM") )
{
BPMSegment new_seg;
new_seg.m_fStartBeat = 0;
@@ -711,17 +741,17 @@ bool Song::LoadFromDWIFile( CString sPath )
m_BPMSegments.Add( new_seg );
SortBPMSegmentsArray( m_BPMSegments );
}
else if( sValueName == "#GAP" )
else if( 0==stricmp(sValueName,"#GAP") )
// the units of GAP is 1/1000 second
m_fBeat0OffsetInSeconds = -atoi( arrayValueTokens[1] ) / 1000.0f;
else if( sValueName == "#SAMPLESTART" )
else if( 0==stricmp(sValueName,"#SAMPLESTART") )
m_fMusicSampleStartSeconds = TimeToSeconds( arrayValueTokens[1] );
else if( sValueName == "#SAMPLELENGTH" )
else if( 0==stricmp(sValueName,"#SAMPLELENGTH") )
m_fMusicSampleLengthSeconds = TimeToSeconds( arrayValueTokens[1] );
else if( sValueName == "#FREEZE" )
else if( 0==stricmp(sValueName,"#FREEZE") )
{
CStringArray arrayFreezeExpressions;
split( arrayValueTokens[1], ",", arrayFreezeExpressions );
@@ -734,12 +764,12 @@ bool Song::LoadFromDWIFile( CString sPath )
float fFreezeBeat = NoteRowToBeat( fIndex );
float fFreezeSeconds = (float)atof( arrayFreezeValues[1] ) / 1000.0f;
AddFreezeSegment( FreezeSegment(fFreezeBeat, fFreezeSeconds) );
AddStopSegment( StopSegment(fFreezeBeat, fFreezeSeconds) );
LOG->WriteLine( "Adding a freeze segment: beat: %f, seconds = %f", fFreezeBeat, fFreezeSeconds );
}
}
else if( sValueName == "#CHANGEBPM" || sValueName == "#BPMCHANGE" )
else if( 0==stricmp(sValueName,"#CHANGEBPM") || 0==stricmp(sValueName,"#BPMCHANGE") )
{
CStringArray arrayBPMChangeExpressions;
split( arrayValueTokens[1], ",", arrayBPMChangeExpressions );
@@ -750,13 +780,13 @@ bool Song::LoadFromDWIFile( CString sPath )
split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues );
float fIndex = atoi( arrayBPMChangeValues[0] ) * ELEMENTS_PER_BEAT / 4.0f;
float fBeat = NoteRowToBeat( fIndex );
float fNewBPM = (float)atoi( arrayBPMChangeValues[1] );
float fNewBPM = (float)atof( arrayBPMChangeValues[1] );
AddBPMSegment( BPMSegment(fBeat, fNewBPM) );
}
}
else if( sValueName == "#SINGLE" || sValueName == "#DOUBLE" || sValueName == "#COUPLE" )
else if( 0==stricmp(sValueName,"#SINGLE") || 0==stricmp(sValueName,"#DOUBLE") || 0==stricmp(sValueName,"#COUPLE") )
{
Notes* pNewNotes = new Notes;
pNewNotes->LoadFromDWITokens(
@@ -766,7 +796,7 @@ bool Song::LoadFromDWIFile( CString sPath )
arrayValueTokens[3],
arrayValueTokens.GetSize() == 5 ? arrayValueTokens[4] : ""
);
m_arrayNotes.Add( pNewNotes );
m_apNotes.Add( pNewNotes );
}
else
// do nothing. We don't care about this value name
@@ -782,7 +812,7 @@ bool Song::LoadFromSMFile( CString sPath )
LOG->WriteLine( "Song::LoadFromSMDir(%s)", sPath );
m_BPMSegments.RemoveAll();
m_FreezeSegments.RemoveAll();
m_StopSegments.RemoveAll();
int i;
@@ -839,49 +869,55 @@ bool Song::LoadFromSMFile( CString sPath )
CString sValueName = arrayValueTokens.GetAt( 0 );
// handle the data
if( sValueName == "#TITLE" )
if( 0==stricmp(sValueName,"#TITLE") )
GetMainAndSubTitlesFromFullTitle( arrayValueTokens[1], m_sMainTitle, m_sSubTitle );
else if( sValueName == "#SUBTITLE" )
else if( 0==stricmp(sValueName,"#SUBTITLE") )
m_sSubTitle = arrayValueTokens[1];
else if( sValueName == "#ARTIST" )
else if( 0==stricmp(sValueName,"#ARTIST") )
m_sArtist = arrayValueTokens[1];
else if( sValueName == "#CREDIT" )
else if( 0==stricmp(sValueName,"#CREDIT") )
m_sCredit = arrayValueTokens[1];
else if( sValueName == "#BANNER" )
else if( 0==stricmp(sValueName,"#BANNER") )
m_sBannerFile = arrayValueTokens[1];
else if( sValueName == "#BACKGROUND" )
else if( 0==stricmp(sValueName,"#BACKGROUND") )
m_sBackgroundFile = arrayValueTokens[1];
// else if( sValueName == "#BACKGROUNDMOVIE" )
// m_sBackgroundMovieFile = arrayValueTokens[1];
else if( sValueName == "#CDTITLE" )
else if( 0==stricmp(sValueName,"#CDTITLE") )
m_sCDTitleFile = arrayValueTokens[1];
else if( sValueName == "#MUSIC" )
else if( 0==stricmp(sValueName,"#MOVIEBACKGROUND") )
m_sMovieBackgroundFile = arrayValueTokens[1];
else if( 0==stricmp(sValueName,"#MUSIC") )
m_sMusicFile = arrayValueTokens[1];
else if( sValueName == "#MUSICBYTES" )
else if( 0==stricmp(sValueName,"#MUSICBYTES") )
m_iMusicBytes = atoi( arrayValueTokens[1] );
else if( sValueName == "#MUSICLENGTH" )
else if( 0==stricmp(sValueName,"#MUSICLENGTH") )
m_fMusicLengthSeconds = (float)atof( arrayValueTokens[1] );
else if( sValueName == "#SAMPLESTART" )
else if( 0==stricmp(sValueName,"#FIRSTBEAT") )
m_fFirstBeat = (float)atof( arrayValueTokens[1] );
else if( 0==stricmp(sValueName,"#LASTBEAT") )
m_fLastBeat = (float)atof( arrayValueTokens[1] );
else if( 0==stricmp(sValueName,"#SAMPLESTART") )
m_fMusicSampleStartSeconds = TimeToSeconds( arrayValueTokens[1] );
else if( sValueName == "#SAMPLELENGTH" )
else if( 0==stricmp(sValueName,"#SAMPLELENGTH") )
m_fMusicSampleLengthSeconds = TimeToSeconds( arrayValueTokens[1] );
else if( sValueName == "#OFFSET" )
else if( 0==stricmp(sValueName,"#OFFSET") )
m_fBeat0OffsetInSeconds = (float)atof( arrayValueTokens[1] );
else if( sValueName == "#FREEZES" )
else if( 0==stricmp(sValueName,"#STOPS") || 0==stricmp(sValueName,"#FREEZES") )
{
CStringArray arrayFreezeExpressions;
split( arrayValueTokens[1], ",", arrayFreezeExpressions );
@@ -893,17 +929,17 @@ bool Song::LoadFromSMFile( CString sPath )
float fFreezeBeat = (float)atof( arrayFreezeValues[0] );
float fFreezeSeconds = (float)atof( arrayFreezeValues[1] );
FreezeSegment new_seg;
StopSegment new_seg;
new_seg.m_fStartBeat = fFreezeBeat;
new_seg.m_fFreezeSeconds = fFreezeSeconds;
new_seg.m_fStopSeconds = fFreezeSeconds;
LOG->WriteLine( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fFreezeSeconds );
LOG->WriteLine( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
AddFreezeSegment( new_seg );
AddStopSegment( new_seg );
}
}
else if( sValueName == "#BPMS" )
else if( 0==stricmp(sValueName,"#BPMS") )
{
CStringArray arrayBPMChangeExpressions;
split( arrayValueTokens[1], ",", arrayBPMChangeExpressions );
@@ -913,7 +949,7 @@ bool Song::LoadFromSMFile( CString sPath )
CStringArray arrayBPMChangeValues;
split( arrayBPMChangeExpressions[b], "=", arrayBPMChangeValues );
float fBeat = (float)atof( arrayBPMChangeValues[0] );
float fNewBPM = (float)atoi( arrayBPMChangeValues[1] );
float fNewBPM = (float)atof( arrayBPMChangeValues[1] );
BPMSegment new_seg;
new_seg.m_fStartBeat = fBeat;
@@ -923,19 +959,36 @@ bool Song::LoadFromSMFile( CString sPath )
}
}
else if( sValueName == "#NOTES" )
else if( 0==stricmp(sValueName,"#ANIMATIONS") )
{
CStringArray arrayAnimationExpressions;
split( arrayValueTokens[1], ",", arrayAnimationExpressions );
for( int b=0; b<arrayAnimationExpressions.GetSize(); b++ )
{
CStringArray arrayAnimationValues;
split( arrayAnimationExpressions[b], "=", arrayAnimationValues );
float fBeat = (float)atof( arrayAnimationValues[0] );
CString sAnimName = arrayAnimationValues[1];
sAnimName.MakeLower();
AddAnimationSegment( AnimationSegment(fBeat, sAnimName) );
}
}
else if( 0==stricmp(sValueName,"#NOTES") )
{
Notes* pNewNotes = NULL;
// Check to see if this notes already has been allocated
for( int j=0; j<m_arrayNotes.GetSize(); j++ )
if( m_arrayNotes[j]->m_NotesType == StringToNotesType(arrayValueTokens[1]) &&
m_arrayNotes[j]->m_sDescription == arrayValueTokens[2] )
pNewNotes = m_arrayNotes[j];
for( int j=0; j<m_apNotes.GetSize(); j++ )
if( m_apNotes[j]->m_NotesType == StringToNotesType(arrayValueTokens[1]) &&
m_apNotes[j]->m_sDescription == arrayValueTokens[2] )
pNewNotes = m_apNotes[j];
if( pNewNotes == NULL ) // we didn't find a match that was already loaded
{
pNewNotes = new Notes;
m_arrayNotes.Add( pNewNotes );
m_apNotes.Add( pNewNotes );
}
if( arrayValueTokens.GetSize() != 7 )
@@ -968,120 +1021,164 @@ void Song::TidyUpData()
if( m_BPMSegments.GetSize() == 0 )
throw RageException( "No #BPM specified in '%s.'", GetSongFilePath() );
if( m_sMusicFile == "" || !DoesFileExist(GetMusicPath()) )
if( !HasMusic() )
{
CStringArray arrayPossibleMusic;
GetDirListing( m_sSongDir + CString("*.mp3"), arrayPossibleMusic );
GetDirListing( m_sSongDir + CString("*.ogg"), arrayPossibleMusic );
GetDirListing( m_sSongDir + CString("*.wav"), arrayPossibleMusic );
if( arrayPossibleMusic.GetSize() != 0 ) // we found a match
if( arrayPossibleMusic.GetSize() > 0 ) // we found a match
m_sMusicFile = arrayPossibleMusic[0];
else
throw RageException( "The song in '%s' is missing a music file. You must place a music file in the song folder or remove the song", m_sSongDir );
}
// Save length of music
if( GetMusicPath() != "" )
{
RageSoundStream sound;
sound.Load( GetMusicPath() );
m_fMusicLengthSeconds = sound.GetLengthSeconds();
}
RageSoundStream sound;
sound.Load( GetMusicPath() );
m_fMusicLengthSeconds = sound.GetLengthSeconds();
//
// Here's the problem: We have a directory full of images. We want to determine which
// image is the banner, which is the background, and which is the CDTitle.
//
//
// First, check the file name for hints.
//
if( !HasBanner() )
{
m_sBannerFile = "";
// find the smallest image in the directory
// find an image with "banner" in the file name
CStringArray arrayPossibleBanners;
GetDirListing( m_sSongDir + CString("*.png"), arrayPossibleBanners );
GetDirListing( m_sSongDir + CString("*.jpg"), arrayPossibleBanners );
GetDirListing( m_sSongDir + CString("*.bmp"), arrayPossibleBanners );
DWORD dwSmallestFileSoFar = 0xFFFFFFFF;
CString sSmallestFileSoFar = "";
for( int i=0; i<arrayPossibleBanners.GetSize(); i++ )
{
DWORD this_size = GetFileSizeInBytes( m_sSongDir + arrayPossibleBanners[i] );
if( this_size < dwSmallestFileSoFar ) // we have a new leader!
{
dwSmallestFileSoFar = this_size;
sSmallestFileSoFar = arrayPossibleBanners[i];
}
}
if( sSmallestFileSoFar != "" ) // we found a match
m_sBannerFile = sSmallestFileSoFar;
else
m_sBannerFile = "";
//throw RageException( ssprintf("Banner could not be found. Please check the Song file '%s' and verify the specified #BANNER exists.", GetSongFilePath()) );
GetDirListing( m_sSongDir + CString("*banner*.png"), arrayPossibleBanners );
GetDirListing( m_sSongDir + CString("*banner*.jpg"), arrayPossibleBanners );
GetDirListing( m_sSongDir + CString("*banner*.bmp"), arrayPossibleBanners );
if( arrayPossibleBanners.GetSize() > 0 )
m_sBannerFile = arrayPossibleBanners[0];
}
if( !HasBackground() )
{
m_sBackgroundFile = "";
// find the largest image in the directory
CStringArray arrayPossibleBackgrounds;
GetDirListing( m_sSongDir + CString("*.png"), arrayPossibleBackgrounds );
GetDirListing( m_sSongDir + CString("*.jpg"), arrayPossibleBackgrounds );
GetDirListing( m_sSongDir + CString("*.bmp"), arrayPossibleBackgrounds );
DWORD dwLargestFileSoFar = 0;
CString sLargestFileSoFar = "";
for( int i=0; i<arrayPossibleBackgrounds.GetSize(); i++ )
{
DWORD this_size = GetFileSizeInBytes( m_sSongDir + arrayPossibleBackgrounds[i] );
if( this_size > dwLargestFileSoFar ) // we have a new leader!
{
dwLargestFileSoFar = this_size;
sLargestFileSoFar = arrayPossibleBackgrounds[i];
}
}
if( sLargestFileSoFar != "" ) // we found a match
m_sBackgroundFile = sLargestFileSoFar;
// find an image with "bg" or "background" in the file name
CStringArray arrayPossibleBGs;
GetDirListing( m_sSongDir + CString("*bg*.png"), arrayPossibleBGs );
GetDirListing( m_sSongDir + CString("*bg*.jpg"), arrayPossibleBGs );
GetDirListing( m_sSongDir + CString("*bg*.bmp"), arrayPossibleBGs );
GetDirListing( m_sSongDir + CString("*background*.png"), arrayPossibleBGs );
GetDirListing( m_sSongDir + CString("*background*.jpg"), arrayPossibleBGs );
GetDirListing( m_sSongDir + CString("*background*.bmp"), arrayPossibleBGs );
if( arrayPossibleBGs.GetSize() > 0 )
m_sBackgroundFile = arrayPossibleBGs[0];
}
// if( !DoesFileExist(GetBackgroundMoviePath()) )
// {
// m_sBackgroundMovieFile = "";
//
// CStringArray arrayPossibleBackgroundMovies;
// GetDirListing( m_sSongDir + CString("*.avi"), arrayPossibleBackgroundMovies );
// GetDirListing( m_sSongDir + CString("*.mpg"), arrayPossibleBackgroundMovies );
// GetDirListing( m_sSongDir + CString("*.mpeg"), arrayPossibleBackgroundMovies );
//
// if( arrayPossibleBackgroundMovies.GetSize() > 0 ) // we found a match
// m_sBackgroundMovieFile = arrayPossibleBackgroundMovies[0];
// }
if( !HasCDTitle() )
{
m_sCDTitleFile = "";
// find an image with "cdtitle" in the file name
CStringArray arrayPossibleCDTitles;
GetDirListing( m_sSongDir + CString("*cdtitle*.png"), arrayPossibleCDTitles );
GetDirListing( m_sSongDir + CString("*cdtitle*.jpg"), arrayPossibleCDTitles );
GetDirListing( m_sSongDir + CString("*cdtitle*.bmp"), arrayPossibleCDTitles );
if( arrayPossibleCDTitles.GetSize() > 0 )
m_sCDTitleFile = arrayPossibleCDTitles[0];
}
for( int i=0; i<m_arrayNotes.GetSize(); i++ )
//
// Now, For the images we still haven't found, look at the image dimensions of the remaining unclassified images.
//
CStringArray arrayImages;
GetDirListing( m_sSongDir + CString("*.png"), arrayImages );
GetDirListing( m_sSongDir + CString("*.jpg"), arrayImages );
GetDirListing( m_sSongDir + CString("*.bmp"), arrayImages );
for( int i=0; i<arrayImages.GetSize(); i++ ) // foreach image
{
Notes* pNotes = m_arrayNotes[i];
// Skip any image that we've already classified
if( HasBanner() && stricmp(GetBannerPath(), arrayImages[i])==0 )
continue; // skip
if( HasBackground() && stricmp(GetBackgroundPath(), arrayImages[i])==0 )
continue; // skip
if( HasCDTitle() && stricmp(GetCDTitlePath(), arrayImages[i])==0 )
continue; // skip
D3DXIMAGE_INFO ddii;
if( !FAILED( D3DXGetImageInfoFromFile( m_sSongDir + arrayImages[i], &ddii ) ) )
{
if( !HasBackground() && ddii.Width >= 320 && ddii.Height >= 240 )
{
m_sBackgroundFile = arrayImages[i];
continue;
}
if( !HasBanner() && 100 < ddii.Width && ddii.Width < 320 && 64 < ddii.Height && ddii.Height < 240 )
{
m_sBannerFile = arrayImages[i];
continue;
}
if( !HasCDTitle() && ddii.Width <= 100 && ddii.Height <= 64 )
{
m_sCDTitleFile = arrayImages[i];
continue;
}
}
}
if( !HasMovieBackground() )
{
CStringArray arrayPossibleMovies;
GetDirListing( m_sSongDir + CString("*movie*.avi"), arrayPossibleMovies );
GetDirListing( m_sSongDir + CString("*movie*.mpg"), arrayPossibleMovies );
GetDirListing( m_sSongDir + CString("*movie*.mpeg"), arrayPossibleMovies );
GetDirListing( m_sSongDir + CString("*.avi"), arrayPossibleMovies );
GetDirListing( m_sSongDir + CString("*.mpg"), arrayPossibleMovies );
GetDirListing( m_sSongDir + CString("*.mpeg"), arrayPossibleMovies );
if( arrayPossibleMovies.GetSize() > 0 )
m_sMovieBackgroundFile = arrayPossibleMovies[0];
}
//
// calculate radar values and first/last beat
//
for( i=0; i<m_apNotes.GetSize(); i++ )
{
Notes* pNotes = m_apNotes[i];
NoteData tempNoteData;
pNotes->GetNoteData( &tempNoteData );
for( int r=0; r<NUM_RADAR_VALUES; r++ )
pNotes->m_fRadarValues[r] = tempNoteData.GetRadarValue( (RadarCategory)r, m_fMusicLengthSeconds );
float fFirstBeat = tempNoteData.GetFirstBeat();
float fLastBeat = tempNoteData.GetLastBeat();
if( m_fFirstBeat == -1 )
m_fFirstBeat = fFirstBeat;
else
m_fFirstBeat = min( m_fFirstBeat, fFirstBeat );
if( m_fLastBeat == -1 )
m_fLastBeat = fLastBeat;
else
m_fLastBeat = max( m_fLastBeat, fLastBeat );
}
}
void Song::GetNotesThatMatch( NotesType nt, CArray<Notes*, Notes*>& arrayAddTo )
{
for( int i=0; i<m_arrayNotes.GetSize(); i++ ) // for each of the Song's Notes
if( m_arrayNotes[i]->m_NotesType == nt )
arrayAddTo.Add( m_arrayNotes[i] );
for( int i=0; i<m_apNotes.GetSize(); i++ ) // for each of the Song's Notes
if( m_apNotes[i]->m_NotesType == nt )
arrayAddTo.Add( m_apNotes[i] );
}
void Song::SaveToCacheFile()
@@ -1138,26 +1235,17 @@ void Song::SaveToSMFile( CString sPath )
fprintf( fp, "#CREDIT:%s;\n", m_sCredit );
fprintf( fp, "#BANNER:%s;\n", m_sBannerFile );
fprintf( fp, "#BACKGROUND:%s;\n", m_sBackgroundFile );
// fprintf( fp, "#BACKGROUNDMOVIE:%s;\n", m_sBackgroundMovieFile );
fprintf( fp, "#CDTITLE:%s;\n", m_sCDTitleFile );
fprintf( fp, "#MOVIEBACKGROUND:%s;\n", m_sMovieBackgroundFile );
fprintf( fp, "#MUSIC:%s;\n", m_sMusicFile );
fprintf( fp, "#MUSICBYTES:%u;\n", m_iMusicBytes );
fprintf( fp, "#MUSICLENGTH:%.2f;\n", m_fMusicLengthSeconds );
fprintf( fp, "#FIRSTBEAT:%.2f;\n", m_fFirstBeat );
fprintf( fp, "#LASTBEAT:%.2f;\n", m_fLastBeat );
fprintf( fp, "#OFFSET:%.2f;\n", m_fBeat0OffsetInSeconds );
fprintf( fp, "#SAMPLESTART:%.2f;\n", m_fMusicSampleStartSeconds );
fprintf( fp, "#SAMPLELENGTH:%.2f;\n", m_fMusicSampleLengthSeconds );
fprintf( fp, "#FREEZES:" );
for( i=0; i<m_FreezeSegments.GetSize(); i++ )
{
FreezeSegment &fs = m_FreezeSegments[i];
fprintf( fp, "%.2f=%.2f", fs.m_fStartBeat, fs.m_fFreezeSeconds );
if( i != m_FreezeSegments.GetSize()-1 )
fprintf( fp, "," );
}
fprintf( fp, ";\n" );
fprintf( fp, "#BPMS:" );
for( i=0; i<m_BPMSegments.GetSize(); i++ )
{
@@ -1168,12 +1256,34 @@ void Song::SaveToSMFile( CString sPath )
fprintf( fp, "," );
}
fprintf( fp, ";\n" );
fprintf( fp, "#STOPS:" );
for( i=0; i<m_StopSegments.GetSize(); i++ )
{
StopSegment &fs = m_StopSegments[i];
fprintf( fp, "%.2f=%.2f", fs.m_fStartBeat, fs.m_fStopSeconds );
if( i != m_StopSegments.GetSize()-1 )
fprintf( fp, "," );
}
fprintf( fp, ";\n" );
fprintf( fp, "#ANIMATIONS:" );
for( i=0; i<m_AnimationSegments.GetSize(); i++ )
{
AnimationSegment &seg = m_AnimationSegments[i];
fprintf( fp, "%.2f=%s", seg.m_fStartBeat, seg.m_sAnimationName );
if( i != m_AnimationSegments.GetSize()-1 )
fprintf( fp, "," );
}
fprintf( fp, ";\n" );
//
// Save all Notes for this file
//
for( i=0; i<m_arrayNotes.GetSize(); i++ )
m_arrayNotes[i]->WriteSMNotesTag( fp );
for( i=0; i<m_apNotes.GetSize(); i++ )
m_apNotes[i]->WriteSMNotesTag( fp );
fclose( fp );
}
+5 -5
View File
@@ -289,11 +289,11 @@ void SongManager::ReadStatisticsFromDisk()
// Search for the corresponding Notes pointer.
Notes* pNotes = NULL;
for( i=0; i<pSong->m_arrayNotes.GetSize(); i++ )
for( i=0; i<pSong->m_apNotes.GetSize(); i++ )
{
if( pSong->m_arrayNotes[i]->m_sDescription == szNotesName ) // match!
if( pSong->m_apNotes[i]->m_sDescription == szNotesName ) // match!
{
pNotes = pSong->m_arrayNotes[i];
pNotes = pSong->m_apNotes[i];
break;
}
}
@@ -330,9 +330,9 @@ void SongManager::SaveStatisticsToDisk()
{
Song* pSong = m_pSongs[i];
for( int j=0; j<pSong->m_arrayNotes.GetSize(); j++ ) // for each Notes
for( int j=0; j<pSong->m_apNotes.GetSize(); j++ ) // for each Notes
{
Notes* pNotes = pSong->m_arrayNotes[j];
Notes* pNotes = pSong->m_apNotes[j];
if( pNotes->m_TopGrade == GRADE_NO_DATA )
continue; // skip
+2 -2
View File
@@ -41,8 +41,8 @@ public:
virtual void DrawPrimitives();
virtual void Update( float fDeltaTime );
virtual void StartAnimating() { m_bIsAnimating = TRUE; };
virtual void StopAnimating() { m_bIsAnimating = FALSE; };
virtual void StartAnimating() { m_bIsAnimating = TRUE; if(m_pTexture) m_pTexture->Play(); };
virtual void StopAnimating() { m_bIsAnimating = FALSE; if(m_pTexture) m_pTexture->Pause(); };
virtual void SetState( int iNewState );
int GetNumStates() { return m_iNumStates; };
+8
View File
@@ -848,6 +848,14 @@ SOURCE=.\Screen.h
# End Source File
# Begin Source File
SOURCE=.\ScreenAppearanceOptions.cpp
# End Source File
# Begin Source File
SOURCE=.\ScreenAppearanceOptions.h
# End Source File
# Begin Source File
SOURCE=.\ScreenCaution.cpp
# End Source File
# Begin Source File
+6
View File
@@ -146,6 +146,12 @@
<File
RelativePath="Screen.h">
</File>
<File
RelativePath="ScreenAppearanceOptions.cpp">
</File>
<File
RelativePath="ScreenAppearanceOptions.h">
</File>
<File
RelativePath="ScreenCaution.cpp">
</File>
+1 -1
View File
@@ -38,7 +38,7 @@ RSC=rc.exe
# PROP BASE Target_Dir ""
# PROP Use_MFC 6
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "../"
# PROP Output_Dir "../../"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c
+2 -2
View File
@@ -166,7 +166,7 @@ void CSmpackageDlg::OnButtonExport()
'+', '=', '[', ']', '{', '}', '|', ':', '\"', '\\',
'<', '>', ',', '?', '/'
};
for( int i=0; i<sizeof(charsToReplace[]); i++ )
for( int i=0; i<sizeof(charsToReplace); i++ )
sZipFileName.Replace( charsToReplace[i], '_' );
CString sZipFilePath = sDesktopPath + sZipFileName;
@@ -192,7 +192,7 @@ void CSmpackageDlg::OnButtonExport()
m_zip.AddNewFile( sGroupDir, 0, true );
m_zip.AddNewFile( sSongDir, 0, true );
for( int i=0; i<arrayFiles.GetSize(); i++ )
for( i=0; i<arrayFiles.GetSize(); i++ )
{
CString sFileName = arrayFiles[i];
CString sFilePath = sSongDir + "\\" + sFileName;
+38 -15
View File
@@ -24,12 +24,20 @@ struct BPMSegment
float m_fBPM;
};
struct FreezeSegment
struct StopSegment
{
FreezeSegment() { m_fStartBeat = m_fFreezeSeconds = -1; };
FreezeSegment( float s, float f ) { m_fStartBeat = s; m_fFreezeSeconds = f; };
StopSegment() { m_fStartBeat = m_fStopSeconds = -1; };
StopSegment( float s, float f ) { m_fStartBeat = s; m_fStopSeconds = f; };
float m_fStartBeat;
float m_fFreezeSeconds;
float m_fStopSeconds;
};
struct AnimationSegment
{
AnimationSegment() { m_fStartBeat = -1; };
AnimationSegment( float s, CString sAnimName ) { m_fStartBeat = s; m_sAnimationName = sAnimName; };
float m_fStartBeat;
CString m_sAnimationName;
};
@@ -66,36 +74,44 @@ public:
CString m_sCredit;
CString GetFullTitle() {return m_sMainTitle + " " + m_sSubTitle; };
static void GetMainAndSubTitlesFromFullTitle( CString sFullTitle, CString &sMainTitleOut, CString &sSubTitleOut );
static void GetMainAndSubTitlesFromFullTitle( const CString sFullTitle, CString &sMainTitleOut, CString &sSubTitleOut );
CString m_sMusicFile;
DWORD m_iMusicBytes;
float m_fBeat0OffsetInSeconds;
float m_fMusicLengthSeconds;
float m_fFirstBeat;
float m_fLastBeat;
float m_fMusicSampleStartSeconds;
float m_fMusicSampleLengthSeconds;
CString m_sBannerFile;
CString m_sBackgroundFile;
CString m_sCDTitleFile;
CString m_sMovieBackgroundFile;
CString GetMusicPath() {return m_sSongDir+m_sMusicFile; };
CString GetBannerPath() {return m_sSongDir+m_sBannerFile; };
CString GetBackgroundPath() {return m_sSongDir+m_sBackgroundFile; };
CString GetCDTitlePath() {return m_sSongDir+m_sCDTitleFile; };
CString GetCDTitlePath() {return m_sCDTitleFile.Find('.')==0 ? m_sCDTitleFile : m_sSongDir+m_sCDTitleFile; };
CString GetMovieBackgroundPath(){return m_sSongDir+m_sMovieBackgroundFile; };
bool HasMusic() {return m_sMusicFile != "" && DoesFileExist(GetMusicPath()); };
bool HasBanner() {return m_sBannerFile != "" && DoesFileExist(GetBannerPath()); };
bool HasBackground() {return m_sBackgroundFile != "" && DoesFileExist(GetBackgroundPath()); };
bool HasCDTitle() {return m_sCDTitleFile != "" && DoesFileExist(GetCDTitlePath()); };
bool HasMusic() {return m_sMusicFile != "" && IsAFile(GetMusicPath()); };
bool HasBanner() {return m_sBannerFile != "" && IsAFile(GetBannerPath()); };
bool HasBackground() {return m_sBackgroundFile != "" && IsAFile(GetBackgroundPath()); };
bool HasCDTitle() {return m_sCDTitleFile != "" && IsAFile(GetCDTitlePath()); };
bool HasMovieBackground() {return m_sMovieBackgroundFile != ""&& IsAFile(GetMovieBackgroundPath()); };
CArray<BPMSegment, BPMSegment&> m_BPMSegments; // this must be sorted before gameplay
CArray<FreezeSegment, FreezeSegment&> m_FreezeSegments; // this must be sorted before gameplay
CArray<StopSegment, StopSegment&> m_StopSegments; // this must be sorted before gameplay
CArray<AnimationSegment, AnimationSegment&> m_AnimationSegments; // this must be sorted before gameplay
void AddBPMSegment( BPMSegment seg );
void AddFreezeSegment( FreezeSegment seg );
void AddStopSegment( StopSegment seg );
void AddAnimationSegment( AnimationSegment seg );
void GetMinMaxBPM( float &fMinBPM, float &fMaxBPM )
{
fMaxBPM = 0;
@@ -114,20 +130,27 @@ public:
break;
return m_BPMSegments[i].m_fBPM;
};
CString GetAnimationAtBeat( float fBeat )
{
for( int i=0; i<m_AnimationSegments.GetSize()-1; i++ )
if( m_AnimationSegments[i+1].m_fStartBeat > fBeat )
break;
return m_AnimationSegments[i].m_sAnimationName;
};
void GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut );
float GetElapsedTimeFromBeat( float fBeat );
CArray<Notes*, Notes*> m_arrayNotes;
CArray<Notes*, Notes*> m_apNotes;
void GetNotesThatMatch( NotesType nt, CArray<Notes*, Notes*>& arrayAddTo );
int GetNumTimesPlayed()
{
int iTotalNumTimesPlayed = 0;
for( int i=0; i<m_arrayNotes.GetSize(); i++ )
for( int i=0; i<m_apNotes.GetSize(); i++ )
{
iTotalNumTimesPlayed += m_arrayNotes[i]->m_iNumTimesPlayed;
iTotalNumTimesPlayed += m_apNotes[i]->m_iNumTimesPlayed;
}
return iTotalNumTimesPlayed;
}