Add nITG's various path shape & other modifiers - V2 (#1435)
* Implemented nITG's Square modifiers Modifiers added: Square SquareOffset SquarePeriod SquareZ SquareZOffset SquareZPeriod * Implemented nITG's BumpyX Modifiers Also fixes up some tiny bits pertaining to the square modifiers. Modifiers Added: BumpyX BumpyXPeriod BumpyXOffset * Implemented nITG's TornadoZ Modifiers Modifiers Added: TornadoZ TornadoZPeriod TornadoZOffset Another commit is needed to update fallback's metrics * Update fallback's metrics to accommodate TornadoX * Implemented nITG's Parabola Modifiers Modifiers Added: ParabolaX ParabolaY ParabolaZ * Implemented nITG's Sawtooth Modifiers Modifiers Added: Sawtooth SawtoothPeriod SawtoothZ SawtoothZPeriod * Implemented nITG's Zigzag Modifiers Modifiers Added: Zigzag ZigzagPeriod ZigzagOffset ZigzagZ ZigzagZPeriod ZigzagZOffset * Implemented nITG's ModTimer modifiers Modifiers Added: ModTimer (Lua method name is ModTimerSetting (takes enums. Ex: 'ModTimerType_Song'). Can be activated with mod strings 'modtimer(song/beat/game/default)' ) ModTimerOffset ModTimerMult * Remove Log use from ArrowEffects::GetTime() * Accidentally removed a CPY(m_BatteryLives) * Implemented nITG's DrunkZ modifiers Modifiers added: drunkz drunkzspeed drunkzoffset drunkzperiod Another commit is needed to update fallback's metrics * Update fallback's metrics to accommodate DrunkZ * Implemented nITG's BeatY & BeatZ Modifers Modifiers Added: beaty beatyoffset beatyperiod beatymult beatz beatzoffset beatzperiod beatzmult Another commit is needed to update fallback's metrics * Updated fallback's metrics to accommodate ... the new Beat modifiers. * Implemented nITG's Digital Modifiers Modifers Added: digital digitalsteps digitalperiod digitaloffset digitalz digitalzsteps digitalzperiod digitalzoffset * Removed duplicate zbuffer check. * Updated Luadocs with the new modifiers * Removed accidental duplicate Mini from Luadocs * Split up long modifier lines. Hopefully, this makes it a bit easier to read. * Remove accidental commit to root of repo. * Split up long modifier lines Hopefully, this makes it easier to read. * Redid Square functions to not use FastSin This implementation is based off of 5.2's square_wave function from ModValue. * Redid zigzag functions to not use FastSin This implementation is based off of 5.2's triangle_wave function from ModValue. * Moved square & zigzag calculation to RageMath. New RageMath functions: RageSquare RageTriangle * Made Square & Digital have the same period... as Zigzag and Sawtooth. * Deduplicate tornado calculations. * Fixed typo in UpdateTornado, and moved UpdateTornado logic to ArrowEffects::Init because it doesn't depend on anything that changes every frame. Tornado metrics are also loaded in ArrowEffects::Init. * Deduplicated Beat mod update logic. The logic is now placed into a function called UpdateBeat. The m_fBeatFactor members are now a 1D array, similar to m_MaxTornado and m_MinTornado.
This commit is contained in:
+307
-85
@@ -14,6 +14,8 @@
|
||||
#include "ThemeMetric.h"
|
||||
#include <float.h>
|
||||
|
||||
static char const dimension_names[4]= "XYZ";
|
||||
|
||||
static ThemeMetric<float> ARROW_SPACING( "ArrowEffects", "ArrowSpacing" );
|
||||
static ThemeMetric<bool> QUANTIZE_ARROW_Y( "ArrowEffects", "QuantizeArrowYPosition");
|
||||
static ThemeMetric<bool> HIDDEN_SUDDEN_PAST_RECEPTOR( "ArrowEffects", "DrawHiddenNotesAfterReceptor");
|
||||
@@ -46,16 +48,34 @@ static ThemeMetric<float> TIPSY_ARROW_MAGNITUDE( "ArrowEffects", "TipsyArrowMagn
|
||||
static ThemeMetric<float> TIPSY_OFFSET_TIMER_FREQUENCY( "ArrowEffects", "TipsyOffsetTimerFrequency" );
|
||||
static ThemeMetric<float> TIPSY_OFFSET_COLUMN_FREQUENCY( "ArrowEffects", "TipsyOffsetColumnFrequency" );
|
||||
static ThemeMetric<float> TIPSY_OFFSET_ARROW_MAGNITUDE( "ArrowEffects", "TipsyOffsetArrowMagnitude" );
|
||||
static ThemeMetric<float> TORNADO_POSITION_SCALE_TO_LOW( "ArrowEffects", "TornadoPositionScaleToLow" );
|
||||
static ThemeMetric<float> TORNADO_POSITION_SCALE_TO_HIGH( "ArrowEffects", "TornadoPositionScaleToHigh" );
|
||||
static ThemeMetric<float> TORNADO_OFFSET_FREQUENCY( "ArrowEffects", "TornadoOffsetFrequency" );
|
||||
static ThemeMetric<float> TORNADO_OFFSET_SCALE_FROM_LOW( "ArrowEffects", "TornadoOffsetScaleFromLow" );
|
||||
static ThemeMetric<float> TORNADO_OFFSET_SCALE_FROM_HIGH( "ArrowEffects", "TornadoOffsetScaleFromHigh" );
|
||||
|
||||
static RString TPSTL_NAME(size_t i) { return ssprintf("Tornado%cPositionScaleToLow", dimension_names[i]); }
|
||||
static ThemeMetric1D<float> TORNADO_POSITION_SCALE_TO_LOW("ArrowEffects", TPSTL_NAME, 3);
|
||||
static RString TPSTH_NAME(size_t i) { return ssprintf("Tornado%cPositionScaleToHigh", dimension_names[i]); }
|
||||
static ThemeMetric1D<float> TORNADO_POSITION_SCALE_TO_HIGH("ArrowEffects", TPSTH_NAME, 3);
|
||||
static RString TOF_NAME(size_t i) { return ssprintf("Tornado%cOffsetFrequency", dimension_names[i]); }
|
||||
static ThemeMetric1D<float> TORNADO_OFFSET_FREQUENCY("ArrowEffects", TOF_NAME, 3);
|
||||
static RString TOSFL_NAME(size_t i) { return ssprintf("Tornado%cOffsetScaleFromLow", dimension_names[i]); }
|
||||
static ThemeMetric1D<float> TORNADO_OFFSET_SCALE_FROM_LOW("ArrowEffects", TOSFL_NAME, 3);
|
||||
static RString TOSFH_NAME(size_t i) { return ssprintf("Tornado%cOffsetScaleFromHigh", dimension_names[i]); }
|
||||
static ThemeMetric1D<float> TORNADO_OFFSET_SCALE_FROM_HIGH("ArrowEffects", TOSFH_NAME, 3);
|
||||
|
||||
static ThemeMetric<float> DRUNK_COLUMN_FREQUENCY( "ArrowEffects", "DrunkColumnFrequency" );
|
||||
static ThemeMetric<float> DRUNK_OFFSET_FREQUENCY( "ArrowEffects", "DrunkOffsetFrequency" );
|
||||
static ThemeMetric<float> DRUNK_ARROW_MAGNITUDE( "ArrowEffects", "DrunkArrowMagnitude" );
|
||||
|
||||
static ThemeMetric<float> DRUNK_Z_COLUMN_FREQUENCY( "ArrowEffects", "DrunkZColumnFrequency" );
|
||||
static ThemeMetric<float> DRUNK_Z_OFFSET_FREQUENCY( "ArrowEffects", "DrunkZOffsetFrequency" );
|
||||
static ThemeMetric<float> DRUNK_Z_ARROW_MAGNITUDE( "ArrowEffects", "DrunkZArrowMagnitude" );
|
||||
|
||||
static ThemeMetric<float> BEAT_OFFSET_HEIGHT( "ArrowEffects", "BeatOffsetHeight" );
|
||||
static ThemeMetric<float> BEAT_PI_HEIGHT( "ArrowEffects", "BeatPIHeight" );
|
||||
|
||||
static ThemeMetric<float> BEAT_Y_OFFSET_HEIGHT( "ArrowEffects", "BeatYOffsetHeight" );
|
||||
static ThemeMetric<float> BEAT_Y_PI_HEIGHT( "ArrowEffects", "BeatYPIHeight" );
|
||||
static ThemeMetric<float> BEAT_Z_OFFSET_HEIGHT( "ArrowEffects", "BeatZOffsetHeight" );
|
||||
static ThemeMetric<float> BEAT_Z_PI_HEIGHT( "ArrowEffects", "BeatZPIHeight" );
|
||||
|
||||
static ThemeMetric<float> TINY_PERCENT_BASE( "ArrowEffects", "TinyPercentBase" );
|
||||
static ThemeMetric<float> TINY_PERCENT_GATE( "ArrowEffects", "TinyPercentGate" );
|
||||
static ThemeMetric<bool> DIZZY_HOLD_HEADS( "ArrowEffects", "DizzyHoldHeads" );
|
||||
@@ -69,21 +89,166 @@ static float GetNoteFieldHeight()
|
||||
return SCREEN_HEIGHT + fabsf(curr_options->m_fPerspectiveTilt)*200;
|
||||
}
|
||||
|
||||
float ArrowEffects::GetTime()
|
||||
{
|
||||
float mult = 1.f + curr_options->m_fModTimerMult;
|
||||
float offset = curr_options->m_fModTimerOffset;
|
||||
ModTimerType modtimer = curr_options->m_ModTimerType;
|
||||
switch(modtimer)
|
||||
{
|
||||
case ModTimerType_Default:
|
||||
case ModTimerType_Game:
|
||||
return (RageTimer::GetTimeSinceStartFast()+offset)*mult;
|
||||
case ModTimerType_Beat:
|
||||
return (GAMESTATE->m_Position.m_fSongBeatVisible+offset)*mult;
|
||||
case ModTimerType_Song:
|
||||
return (GAMESTATE->m_Position.m_fMusicSeconds+offset)*mult;
|
||||
default:
|
||||
return RageTimer::GetTimeSinceStartFast()+offset;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct PerPlayerData
|
||||
{
|
||||
float m_fMinTornadoX[MAX_COLS_PER_PLAYER];
|
||||
float m_fMaxTornadoX[MAX_COLS_PER_PLAYER];
|
||||
float m_MinTornado[3][MAX_COLS_PER_PLAYER];
|
||||
float m_MaxTornado[3][MAX_COLS_PER_PLAYER];
|
||||
float m_fInvertDistance[MAX_COLS_PER_PLAYER];
|
||||
float m_tipsy_result[MAX_COLS_PER_PLAYER];
|
||||
float m_tipsy_offset_result[MAX_COLS_PER_PLAYER];
|
||||
float m_fBeatFactor;
|
||||
float m_fBeatFactor[3];
|
||||
float m_fExpandSeconds;
|
||||
|
||||
// m_prev_style is for checking whether ArrowEffects::Init needs to be
|
||||
// called. Finding all the placed ArrowEffects is used and making sure
|
||||
// they all call Init after changing style is non-trivial and more likely
|
||||
// to cause bugs. -Kyz
|
||||
Style const* m_prev_style;
|
||||
};
|
||||
PerPlayerData g_EffectData[NUM_PLAYERS];
|
||||
int const dim_x= 0;
|
||||
int const dim_y= 1;
|
||||
int const dim_z= 2;
|
||||
|
||||
float tornado_position_scale_to_low[3];
|
||||
float tornado_position_scale_to_high[3];
|
||||
float tornado_offset_frequency[3];
|
||||
float tornado_offset_scale_from_low[3];
|
||||
float tornado_offset_scale_from_high[3];
|
||||
};
|
||||
|
||||
static float CalculateTornadoOffsetFromMagnitude(int dimension, int col_id,
|
||||
float magnitude, float effect_offset, float period,
|
||||
const Style::ColumnInfo* pCols, float field_zoom,
|
||||
PerPlayerData& data, float y_offset)
|
||||
{
|
||||
float const real_pixel_offset= pCols[col_id].fXOffset * field_zoom;
|
||||
float const position_between= SCALE(real_pixel_offset,
|
||||
data.m_MinTornado[dimension][col_id] * field_zoom,
|
||||
data.m_MaxTornado[dimension][col_id] * field_zoom,
|
||||
tornado_position_scale_to_low[dimension],
|
||||
tornado_position_scale_to_high[dimension]);
|
||||
float rads= acosf(position_between);
|
||||
float frequency= tornado_offset_frequency[dimension];
|
||||
rads+= (y_offset + effect_offset) * ((period * frequency) + frequency) / SCREEN_HEIGHT;
|
||||
float const adjusted_pixel_offset= SCALE(RageFastCos(rads),
|
||||
tornado_offset_scale_from_low[dimension],
|
||||
tornado_offset_scale_from_high[dimension],
|
||||
data.m_MinTornado[dimension][col_id] * field_zoom,
|
||||
data.m_MaxTornado[dimension][col_id] * field_zoom);
|
||||
return (adjusted_pixel_offset - real_pixel_offset) * magnitude;
|
||||
}
|
||||
|
||||
static void UpdateBeat(int dimension, PerPlayerData &data, const SongPosition &position, float beat_offset, float beat_mult)
|
||||
{
|
||||
float fAccelTime = 0.2f, fTotalTime = 0.5f;
|
||||
float fBeat = ((position.m_fSongBeatVisible + fAccelTime + beat_offset) * (beat_mult+1));
|
||||
|
||||
const bool bEvenBeat = ( int(fBeat) % 2 ) != 0;
|
||||
|
||||
data.m_fBeatFactor[dimension] = 0;
|
||||
if( fBeat < 0 )
|
||||
return;
|
||||
|
||||
// -100.2 -> -0.2 -> 0.2
|
||||
fBeat -= truncf( fBeat );
|
||||
fBeat += 1;
|
||||
fBeat -= truncf( fBeat );
|
||||
|
||||
if( fBeat >= fTotalTime )
|
||||
return;
|
||||
|
||||
if( fBeat < fAccelTime )
|
||||
{
|
||||
data.m_fBeatFactor[dimension] = SCALE( fBeat, 0.0f, fAccelTime, 0.0f, 1.0f);
|
||||
data.m_fBeatFactor[dimension] *= data.m_fBeatFactor[dimension];
|
||||
} else /* fBeat < fTotalTime */ {
|
||||
data.m_fBeatFactor[dimension] = SCALE( fBeat, fAccelTime, fTotalTime, 1.0f, 0.0f);
|
||||
data.m_fBeatFactor[dimension] = 1 - (1-data.m_fBeatFactor[dimension]) * (1-data.m_fBeatFactor[dimension]);
|
||||
}
|
||||
|
||||
if( bEvenBeat )
|
||||
data.m_fBeatFactor[dimension] *= -1;
|
||||
data.m_fBeatFactor[dimension] *= 20.0f;
|
||||
}
|
||||
|
||||
|
||||
void ArrowEffects::Init(PlayerNumber pn)
|
||||
{
|
||||
const Style* pStyle = GAMESTATE->GetCurrentStyle(pn);
|
||||
const Style::ColumnInfo* pCols = pStyle->m_ColumnInfo[pn];
|
||||
PerPlayerData &data = g_EffectData[pn];
|
||||
// Init tornado limits.
|
||||
// This used to run every frame, but it doesn't actually depend on anything
|
||||
// that changes every frame. In openitg, it runs for every note. -Kyz
|
||||
|
||||
// TRICKY: Tornado is very unplayable in doubles, so use a smaller
|
||||
// tornado width if there are many columns
|
||||
|
||||
/* the wide_field check makes an assumption for dance mode.
|
||||
* perhaps check if we are actually playing on singles without,
|
||||
* say more than 6 columns. That would exclude IIDX, pop'n, and
|
||||
* techno-8, all of which would be very hectic.
|
||||
* certain non-singles modes (like halfdoubles 6cols)
|
||||
* could possibly have tornado enabled.
|
||||
* let's also take default resolution (640x480) into mind. -aj */
|
||||
bool wide_field= pStyle->m_iColsPerPlayer > 4;
|
||||
int max_player_col= pStyle->m_iColsPerPlayer-1;
|
||||
for(int dimension= 0; dimension < 3; ++dimension)
|
||||
{
|
||||
int width= 3;
|
||||
// wide_field only matters for x, which is dimension 0. -Kyz
|
||||
if(dimension == 0 && wide_field)
|
||||
{
|
||||
width= 2;
|
||||
}
|
||||
for(int col_id= 0; col_id <= max_player_col; ++col_id)
|
||||
{
|
||||
int start_col= col_id - width;
|
||||
int end_col= col_id + width;
|
||||
CLAMP(start_col, 0, max_player_col);
|
||||
CLAMP(end_col, 0, max_player_col);
|
||||
data.m_MinTornado[dimension][col_id]= FLT_MAX;
|
||||
data.m_MaxTornado[dimension][col_id]= FLT_MIN;
|
||||
for(int i= start_col; i <= end_col; ++i)
|
||||
{
|
||||
// Using the x offset when the dimension might be y or z feels so
|
||||
// wrong, but it provides min and max values when otherwise the
|
||||
// limits would just be zero, which would make it do nothing. -Kyz
|
||||
data.m_MinTornado[dimension][col_id] = min(pCols[i].fXOffset, data.m_MinTornado[dimension][col_id]);
|
||||
data.m_MaxTornado[dimension][col_id] = max(pCols[i].fXOffset, data.m_MaxTornado[dimension][col_id]);
|
||||
}
|
||||
}
|
||||
|
||||
tornado_position_scale_to_low[dimension]= TORNADO_POSITION_SCALE_TO_LOW.GetValue(dimension);
|
||||
tornado_position_scale_to_high[dimension]= TORNADO_POSITION_SCALE_TO_HIGH.GetValue(dimension);
|
||||
tornado_offset_frequency[dimension]= TORNADO_OFFSET_FREQUENCY.GetValue(dimension);
|
||||
tornado_offset_scale_from_low[dimension]= TORNADO_OFFSET_SCALE_FROM_LOW.GetValue(dimension);
|
||||
tornado_offset_scale_from_high[dimension]= TORNADO_OFFSET_SCALE_FROM_HIGH.GetValue(dimension);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrowEffects::Update()
|
||||
{
|
||||
static float fLastTime = 0;
|
||||
@@ -101,42 +266,17 @@ void ArrowEffects::Update()
|
||||
|
||||
PerPlayerData &data = g_EffectData[pn];
|
||||
|
||||
if(pStyle != data.m_prev_style)
|
||||
{
|
||||
Init(pn);
|
||||
data.m_prev_style= pStyle;
|
||||
}
|
||||
|
||||
if( !position.m_bFreeze || !position.m_bDelay )
|
||||
{
|
||||
data.m_fExpandSeconds += fTime - fLastTime;
|
||||
data.m_fExpandSeconds = fmodf( data.m_fExpandSeconds, (PI*2)/(accels[PlayerOptions::ACCEL_EXPAND_PERIOD]+1) );
|
||||
}
|
||||
|
||||
// Update Tornado
|
||||
for( int iColNum = 0; iColNum < MAX_COLS_PER_PLAYER; ++iColNum )
|
||||
{
|
||||
// TRICKY: Tornado is very unplayable in doubles, so use a smaller
|
||||
// tornado width if there are many columns
|
||||
|
||||
/* the below makes an assumption for dance mode.
|
||||
* perhaps check if we are actually playing on singles without,
|
||||
* say more than 6 columns. That would exclude IIDX, pop'n, and
|
||||
* techno-8, all of which would be very hectic.
|
||||
* certain non-singles modes (like halfdoubles 6cols)
|
||||
* could possibly have tornado enabled.
|
||||
* let's also take default resolution (640x480) into mind. -aj */
|
||||
bool bWideField = pStyle->m_iColsPerPlayer > 4;
|
||||
int iTornadoWidth = bWideField ? 2 : 3;
|
||||
|
||||
int iStartCol = iColNum - iTornadoWidth;
|
||||
int iEndCol = iColNum + iTornadoWidth;
|
||||
CLAMP( iStartCol, 0, pStyle->m_iColsPerPlayer-1 );
|
||||
CLAMP( iEndCol, 0, pStyle->m_iColsPerPlayer-1 );
|
||||
|
||||
data.m_fMinTornadoX[iColNum] = FLT_MAX;
|
||||
data.m_fMaxTornadoX[iColNum] = FLT_MIN;
|
||||
|
||||
for( int i=iStartCol; i<=iEndCol; i++ )
|
||||
{
|
||||
data.m_fMinTornadoX[iColNum] = min( data.m_fMinTornadoX[iColNum], pCols[i].fXOffset * field_zoom );
|
||||
data.m_fMaxTornadoX[iColNum] = max( data.m_fMaxTornadoX[iColNum], pCols[i].fXOffset * field_zoom);
|
||||
}
|
||||
}
|
||||
|
||||
// Update Invert
|
||||
for( int iColNum = 0; iColNum < MAX_COLS_PER_PLAYER; ++iColNum )
|
||||
@@ -185,7 +325,7 @@ void ArrowEffects::Update()
|
||||
// Update Tipsy
|
||||
if(effects[PlayerOptions::EFFECT_TIPSY] != 0)
|
||||
{
|
||||
const float time= RageTimer::GetTimeSinceStartFast();
|
||||
const float time= ArrowEffects::GetTime();
|
||||
const float time_times_timer= time * ((effects[PlayerOptions::EFFECT_TIPSY_SPEED] * TIPSY_TIMER_FREQUENCY) + TIPSY_TIMER_FREQUENCY);
|
||||
const float arrow_times_mag= ARROW_SIZE * TIPSY_ARROW_MAGNITUDE;
|
||||
const float time_times_offset_timer= time *
|
||||
@@ -211,37 +351,13 @@ void ArrowEffects::Update()
|
||||
}
|
||||
|
||||
// Update Beat
|
||||
do {
|
||||
float fAccelTime = 0.2f, fTotalTime = 0.5f;
|
||||
float fBeat = ((position.m_fSongBeatVisible + fAccelTime + effects[PlayerOptions::EFFECT_BEAT_OFFSET]) * (effects[PlayerOptions::EFFECT_BEAT_MULT]+1));
|
||||
UpdateBeat(dim_x, data, position, effects[PlayerOptions::EFFECT_BEAT_OFFSET], effects[PlayerOptions::EFFECT_BEAT_MULT]);
|
||||
|
||||
const bool bEvenBeat = ( int(fBeat) % 2 ) != 0;
|
||||
// Update BeatY
|
||||
UpdateBeat(dim_y, data, position, effects[PlayerOptions::EFFECT_BEAT_Y_OFFSET], effects[PlayerOptions::EFFECT_BEAT_Y_MULT]);
|
||||
|
||||
data.m_fBeatFactor = 0;
|
||||
if( fBeat < 0 )
|
||||
break;
|
||||
|
||||
// -100.2 -> -0.2 -> 0.2
|
||||
fBeat -= truncf( fBeat );
|
||||
fBeat += 1;
|
||||
fBeat -= truncf( fBeat );
|
||||
|
||||
if( fBeat >= fTotalTime )
|
||||
break;
|
||||
|
||||
if( fBeat < fAccelTime )
|
||||
{
|
||||
data.m_fBeatFactor = SCALE( fBeat, 0.0f, fAccelTime, 0.0f, 1.0f);
|
||||
data.m_fBeatFactor *= data.m_fBeatFactor;
|
||||
} else /* fBeat < fTotalTime */ {
|
||||
data.m_fBeatFactor = SCALE( fBeat, fAccelTime, fTotalTime, 1.0f, 0.0f);
|
||||
data.m_fBeatFactor = 1 - (1-data.m_fBeatFactor) * (1-data.m_fBeatFactor);
|
||||
}
|
||||
|
||||
if( bEvenBeat )
|
||||
data.m_fBeatFactor *= -1;
|
||||
data.m_fBeatFactor *= 20.0f;
|
||||
} while( false );
|
||||
// Update BeatZ
|
||||
UpdateBeat(dim_z, data, position, effects[PlayerOptions::EFFECT_BEAT_Z_OFFSET], effects[PlayerOptions::EFFECT_BEAT_Z_MULT]);
|
||||
}
|
||||
fLastTime = fTime;
|
||||
}
|
||||
@@ -337,7 +453,7 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float
|
||||
}
|
||||
|
||||
const float* fAccels = curr_options->m_fAccels;
|
||||
//const float* fEffects = curr_options->m_fEffects;
|
||||
const float* fEffects = curr_options->m_fEffects;
|
||||
|
||||
float fYAdjust = 0; // fill this in depending on PlayerOptions
|
||||
|
||||
@@ -362,6 +478,9 @@ float ArrowEffects::GetYOffset( const PlayerState* pPlayerState, int iCol, float
|
||||
}
|
||||
if( fAccels[PlayerOptions::ACCEL_WAVE] != 0 )
|
||||
fYAdjust += fAccels[PlayerOptions::ACCEL_WAVE] * WAVE_MOD_MAGNITUDE *RageFastSin( fYOffset/((fAccels[PlayerOptions::ACCEL_WAVE_PERIOD]*WAVE_MOD_HEIGHT)+WAVE_MOD_HEIGHT) );
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_PARABOLA_Y] != 0 )
|
||||
fYAdjust += fEffects[PlayerOptions::EFFECT_PARABOLA_Y] * (fYOffset/ARROW_SIZE) * (fYOffset/ARROW_SIZE);
|
||||
|
||||
fYOffset += fYAdjust;
|
||||
|
||||
@@ -449,6 +568,12 @@ float ArrowEffects::GetYPos(int iCol, float fYOffset, float fYReverseOffsetPixel
|
||||
PerPlayerData& data= g_EffectData[curr_options->m_pn];
|
||||
f+= fEffects[PlayerOptions::EFFECT_TIPSY] * data.m_tipsy_result[iCol];
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_BEAT_Y] != 0 )
|
||||
{
|
||||
const float fShift = data.m_fBeatFactor[dim_y]*RageFastSin( fYOffset / ((fEffects[PlayerOptions::EFFECT_BEAT_Y_PERIOD]*BEAT_Y_OFFSET_HEIGHT)+BEAT_Y_OFFSET_HEIGHT) + PI/BEAT_Y_PI_HEIGHT );
|
||||
f += fEffects[PlayerOptions::EFFECT_BEAT_Y] * fShift;
|
||||
}
|
||||
|
||||
// In beware's DDR Extreme-focused fork of StepMania 3.9, this value is
|
||||
// floored, making arrows show on integer Y coordinates. Supposedly it makes
|
||||
// the arrows look better, but testing needs to be done.
|
||||
@@ -466,6 +591,8 @@ float ArrowEffects::GetYOffsetFromYPos(int iCol, float YPos, float fYReverseOffs
|
||||
// TODO: Don't index by PlayerNumber.
|
||||
PerPlayerData& data= g_EffectData[curr_options->m_pn];
|
||||
f+= fEffects[PlayerOptions::EFFECT_TIPSY] * data.m_tipsy_offset_result[iCol];
|
||||
|
||||
f+= fEffects[PlayerOptions::EFFECT_PARABOLA_Y] * (YPos/ARROW_SIZE) * (YPos/ARROW_SIZE);
|
||||
|
||||
float fShift, fScale;
|
||||
ArrowGetReverseShiftAndScale(iCol, fYReverseOffsetPixels, fShift, fScale);
|
||||
@@ -490,22 +617,21 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_TORNADO] != 0 )
|
||||
{
|
||||
const float fRealPixelOffset = pCols[iColNum].fXOffset * pPlayerState->m_NotefieldZoom;
|
||||
const float fPositionBetween = SCALE( fRealPixelOffset, data.m_fMinTornadoX[iColNum], data.m_fMaxTornadoX[iColNum],
|
||||
TORNADO_POSITION_SCALE_TO_LOW, TORNADO_POSITION_SCALE_TO_HIGH );
|
||||
float fRads = acosf( fPositionBetween );
|
||||
fRads += (fYOffset + fEffects[PlayerOptions::EFFECT_TORNADO_OFFSET]) * ((fEffects[PlayerOptions::EFFECT_TORNADO_PERIOD] * TORNADO_OFFSET_FREQUENCY) + TORNADO_OFFSET_FREQUENCY) / SCREEN_HEIGHT;
|
||||
|
||||
const float fAdjustedPixelOffset = SCALE( RageFastCos(fRads), TORNADO_OFFSET_SCALE_FROM_LOW, TORNADO_OFFSET_SCALE_FROM_HIGH,
|
||||
data.m_fMinTornadoX[iColNum], data.m_fMaxTornadoX[iColNum] );
|
||||
|
||||
fPixelOffsetFromCenter += (fAdjustedPixelOffset - fRealPixelOffset) * fEffects[PlayerOptions::EFFECT_TORNADO];
|
||||
fPixelOffsetFromCenter += CalculateTornadoOffsetFromMagnitude(dim_x,
|
||||
iColNum, fEffects[PlayerOptions::EFFECT_TORNADO],
|
||||
fEffects[PlayerOptions::EFFECT_TORNADO_OFFSET],
|
||||
fEffects[PlayerOptions::EFFECT_TORNADO_PERIOD],
|
||||
pCols, pPlayerState->m_NotefieldZoom, data, fYOffset);
|
||||
}
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_BUMPY_X] != 0 )
|
||||
fPixelOffsetFromCenter += fEffects[PlayerOptions::EFFECT_BUMPY_X] * 40*RageFastSin( (fYOffset+(100.0f*(fEffects[PlayerOptions::EFFECT_BUMPY_X_OFFSET])))/((fEffects[PlayerOptions::EFFECT_BUMPY_X_PERIOD]*16.0f)+16.0f) );
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_DRUNK] != 0 )
|
||||
fPixelOffsetFromCenter += fEffects[PlayerOptions::EFFECT_DRUNK] *
|
||||
( RageFastCos( RageTimer::GetTimeSinceStartFast()*(1+fEffects[PlayerOptions::EFFECT_DRUNK_SPEED]) + iColNum*((fEffects[PlayerOptions::EFFECT_DRUNK_OFFSET]*DRUNK_COLUMN_FREQUENCY)+DRUNK_COLUMN_FREQUENCY)
|
||||
( RageFastCos( GetTime()*(1+fEffects[PlayerOptions::EFFECT_DRUNK_SPEED]) + iColNum*((fEffects[PlayerOptions::EFFECT_DRUNK_OFFSET]*DRUNK_COLUMN_FREQUENCY)+DRUNK_COLUMN_FREQUENCY)
|
||||
+ fYOffset*((fEffects[PlayerOptions::EFFECT_DRUNK_PERIOD]*DRUNK_OFFSET_FREQUENCY)+DRUNK_OFFSET_FREQUENCY)/SCREEN_HEIGHT) * ARROW_SIZE*DRUNK_ARROW_MAGNITUDE );
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_FLIP] != 0 )
|
||||
{
|
||||
const int iFirstCol = 0;
|
||||
@@ -521,9 +647,39 @@ float ArrowEffects::GetXPos( const PlayerState* pPlayerState, int iColNum, float
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_BEAT] != 0 )
|
||||
{
|
||||
const float fShift = data.m_fBeatFactor*RageFastSin( fYOffset / ((fEffects[PlayerOptions::EFFECT_BEAT_PERIOD]*BEAT_OFFSET_HEIGHT)+BEAT_OFFSET_HEIGHT) + PI/BEAT_PI_HEIGHT );
|
||||
const float fShift = data.m_fBeatFactor[dim_x]*RageFastSin( fYOffset / ((fEffects[PlayerOptions::EFFECT_BEAT_PERIOD]*BEAT_OFFSET_HEIGHT)+BEAT_OFFSET_HEIGHT) + PI/BEAT_PI_HEIGHT );
|
||||
fPixelOffsetFromCenter += fEffects[PlayerOptions::EFFECT_BEAT] * fShift;
|
||||
}
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_ZIGZAG] != 0 )
|
||||
{
|
||||
float fResult = RageTriangle( (PI * (1/(fEffects[PlayerOptions::EFFECT_ZIGZAG_PERIOD]+1)) *
|
||||
((fYOffset+(100.0f*(fEffects[PlayerOptions::EFFECT_ZIGZAG_OFFSET])))/ARROW_SIZE) ) );
|
||||
|
||||
fPixelOffsetFromCenter += (fEffects[PlayerOptions::EFFECT_ZIGZAG]*ARROW_SIZE/2) * fResult;
|
||||
}
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_SAWTOOTH] != 0 )
|
||||
fPixelOffsetFromCenter += (fEffects[PlayerOptions::EFFECT_SAWTOOTH]*ARROW_SIZE) *
|
||||
((0.5f / (fEffects[PlayerOptions::EFFECT_SAWTOOTH_PERIOD]+1) * fYOffset) / ARROW_SIZE -
|
||||
floor((0.5f / (fEffects[PlayerOptions::EFFECT_SAWTOOTH_PERIOD]+1) * fYOffset) / ARROW_SIZE) );
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_PARABOLA_X] != 0 )
|
||||
fPixelOffsetFromCenter += fEffects[PlayerOptions::EFFECT_PARABOLA_X] * (fYOffset/ARROW_SIZE) * (fYOffset/ARROW_SIZE);
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_DIGITAL] != 0 )
|
||||
fPixelOffsetFromCenter += (fEffects[PlayerOptions::EFFECT_DIGITAL] * ARROW_SIZE * 0.5f) *
|
||||
round((fEffects[PlayerOptions::EFFECT_DIGITAL_STEPS]+1) * RageFastSin(
|
||||
(PI * (fYOffset + (1.0f * (fEffects[PlayerOptions::EFFECT_DIGITAL_OFFSET]) ) ) /
|
||||
(ARROW_SIZE + (fEffects[PlayerOptions::EFFECT_DIGITAL_PERIOD] * ARROW_SIZE)) ) ) )/(fEffects[PlayerOptions::EFFECT_DIGITAL_STEPS]+1);
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_SQUARE] != 0 )
|
||||
{
|
||||
float fResult = RageSquare( (PI * (fYOffset+(1.0f*(fEffects[PlayerOptions::EFFECT_SQUARE_OFFSET]))) /
|
||||
(ARROW_SIZE+(fEffects[PlayerOptions::EFFECT_SQUARE_PERIOD]*ARROW_SIZE))) );
|
||||
|
||||
fPixelOffsetFromCenter += (fEffects[PlayerOptions::EFFECT_SQUARE] * ARROW_SIZE * 0.5f) * fResult;
|
||||
}
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_XMODE] != 0 )
|
||||
{
|
||||
@@ -791,7 +947,7 @@ float ArrowGetPercentVisible(float fYPosWithoutReverse)
|
||||
fVisibleAdjust -= fAppearances[PlayerOptions::APPEARANCE_STEALTH];
|
||||
if( fAppearances[PlayerOptions::APPEARANCE_BLINK] != 0 )
|
||||
{
|
||||
float f = RageFastSin(RageTimer::GetTimeSinceStartFast()*10);
|
||||
float f = RageFastSin(ArrowEffects::GetTime()*10);
|
||||
f = Quantize( f, BLINK_MOD_FREQUENCY );
|
||||
fVisibleAdjust += SCALE( f, 0, 1, -1, 0 );
|
||||
}
|
||||
@@ -853,13 +1009,67 @@ float ArrowEffects::GetBrightness( const PlayerState* pPlayerState, float fNoteB
|
||||
}
|
||||
|
||||
|
||||
float ArrowEffects::GetZPos(int iCol, float fYOffset)
|
||||
float ArrowEffects::GetZPos( const PlayerState* pPlayerState, int iCol, float fYOffset)
|
||||
{
|
||||
float fZPos=0;
|
||||
const float* fEffects = curr_options->m_fEffects;
|
||||
const Style* pStyle = GAMESTATE->GetCurrentStyle(pPlayerState->m_PlayerNumber);
|
||||
|
||||
// TODO: Don't index by PlayerNumber.
|
||||
const Style::ColumnInfo* pCols = pStyle->m_ColumnInfo[pPlayerState->m_PlayerNumber];
|
||||
PerPlayerData &data = g_EffectData[pPlayerState->m_PlayerNumber];
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_TORNADO_Z] != 0 )
|
||||
{
|
||||
fZPos += CalculateTornadoOffsetFromMagnitude(dim_z, iCol,
|
||||
fEffects[PlayerOptions::EFFECT_TORNADO_Z],
|
||||
fEffects[PlayerOptions::EFFECT_TORNADO_Z_OFFSET],
|
||||
fEffects[PlayerOptions::EFFECT_TORNADO_Z_PERIOD],
|
||||
pCols, pPlayerState->m_NotefieldZoom, data, fYOffset);
|
||||
}
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_BUMPY] != 0 )
|
||||
fZPos += fEffects[PlayerOptions::EFFECT_BUMPY] * 40*RageFastSin( (fYOffset+(100.0f*fEffects[PlayerOptions::EFFECT_BUMPY_OFFSET]) )/((fEffects[PlayerOptions::EFFECT_BUMPY_PERIOD]*16.0f)+16.0f) );
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_ZIGZAG_Z] != 0 )
|
||||
{
|
||||
float fResult = RageTriangle( (PI * (1/(fEffects[PlayerOptions::EFFECT_ZIGZAG_Z_PERIOD]+1)) *
|
||||
((fYOffset+(100.0f*(fEffects[PlayerOptions::EFFECT_ZIGZAG_Z_OFFSET])))/ARROW_SIZE) ) );
|
||||
|
||||
fZPos += (fEffects[PlayerOptions::EFFECT_ZIGZAG_Z]*ARROW_SIZE/2) * fResult;
|
||||
}
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_SAWTOOTH_Z] != 0 )
|
||||
fZPos += (fEffects[PlayerOptions::EFFECT_SAWTOOTH_Z]*ARROW_SIZE) *
|
||||
((0.5f/(fEffects[PlayerOptions::EFFECT_SAWTOOTH_Z_PERIOD]+1)*fYOffset)/ARROW_SIZE -
|
||||
floor((0.5f/(fEffects[PlayerOptions::EFFECT_SAWTOOTH_Z_PERIOD]+1)*fYOffset)/ARROW_SIZE));
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_PARABOLA_Z] != 0 )
|
||||
fZPos += fEffects[PlayerOptions::EFFECT_PARABOLA_Z] * (fYOffset/ARROW_SIZE) * (fYOffset/ARROW_SIZE);
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_DRUNK_Z] != 0 )
|
||||
fZPos += fEffects[PlayerOptions::EFFECT_DRUNK_Z] *
|
||||
( RageFastCos( GetTime()*(1+fEffects[PlayerOptions::EFFECT_DRUNK_Z_SPEED]) + iCol*((fEffects[PlayerOptions::EFFECT_DRUNK_Z_OFFSET]*DRUNK_Z_COLUMN_FREQUENCY)+DRUNK_Z_COLUMN_FREQUENCY)
|
||||
+ fYOffset*((fEffects[PlayerOptions::EFFECT_DRUNK_Z_PERIOD]*DRUNK_Z_OFFSET_FREQUENCY)+DRUNK_Z_OFFSET_FREQUENCY)/SCREEN_HEIGHT) * ARROW_SIZE*DRUNK_Z_ARROW_MAGNITUDE );
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_BEAT_Z] != 0 )
|
||||
{
|
||||
const float fShift = data.m_fBeatFactor[dim_z]*RageFastSin( fYOffset / ((fEffects[PlayerOptions::EFFECT_BEAT_Z_PERIOD]*BEAT_Z_OFFSET_HEIGHT)+BEAT_Z_OFFSET_HEIGHT) + PI/BEAT_Z_PI_HEIGHT );
|
||||
fZPos += fEffects[PlayerOptions::EFFECT_BEAT_Z] * fShift;
|
||||
}
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_DIGITAL_Z] != 0 )
|
||||
fZPos += (fEffects[PlayerOptions::EFFECT_DIGITAL_Z] * ARROW_SIZE * 0.5f) *
|
||||
round((fEffects[PlayerOptions::EFFECT_DIGITAL_Z_STEPS]+1) * RageFastSin(
|
||||
(PI * (fYOffset + (1.0f * (fEffects[PlayerOptions::EFFECT_DIGITAL_Z_OFFSET]) ) ) /
|
||||
(ARROW_SIZE + (fEffects[PlayerOptions::EFFECT_DIGITAL_Z_PERIOD] * ARROW_SIZE)) )))/(fEffects[PlayerOptions::EFFECT_DIGITAL_Z_STEPS]+1);
|
||||
|
||||
if( fEffects[PlayerOptions::EFFECT_SQUARE_Z] != 0 )
|
||||
{
|
||||
float fResult = RageSquare( (PI * (fYOffset+(1.0f*(fEffects[PlayerOptions::EFFECT_SQUARE_Z_OFFSET]))) /
|
||||
(ARROW_SIZE+(fEffects[PlayerOptions::EFFECT_SQUARE_Z_PERIOD]*ARROW_SIZE))) );
|
||||
fZPos += (fEffects[PlayerOptions::EFFECT_SQUARE_Z] * ARROW_SIZE * 0.5f) * fResult;
|
||||
}
|
||||
|
||||
return fZPos;
|
||||
}
|
||||
@@ -874,6 +1084,18 @@ bool ArrowEffects::NeedZBuffer()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if( fEffects[PlayerOptions::EFFECT_BEAT_Z] != 0 ||
|
||||
fEffects[PlayerOptions::EFFECT_DIGITAL_Z] != 0 )
|
||||
return true;
|
||||
if( fEffects[PlayerOptions::EFFECT_ZIGZAG_Z] != 0 ||
|
||||
fEffects[PlayerOptions::EFFECT_SAWTOOTH_Z] != 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if( fEffects[PlayerOptions::EFFECT_PARABOLA_Z] != 0 )
|
||||
return true;
|
||||
if( fEffects[PlayerOptions::EFFECT_SQUARE_Z] != 0 )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1000,7 +1222,7 @@ namespace
|
||||
{
|
||||
PlayerState *ps = Luna<PlayerState>::check( L, 1 );
|
||||
ArrowEffects::SetCurrentOptions(&ps->m_PlayerOptions.GetCurrent());
|
||||
lua_pushnumber(L, ArrowEffects::GetZPos(IArg(2)-1, FArg(3)));
|
||||
lua_pushnumber(L, ArrowEffects::GetZPos( ps, IArg(2)-1, FArg(3)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user