diff options
-rw-r--r-- | Lua/src/base/USingScores.pas | 103 | ||||
-rw-r--r-- | Lua/src/base/USong.pas | 28 | ||||
-rw-r--r-- | Lua/src/screens/UScreenSing.pas | 4 |
3 files changed, 125 insertions, 10 deletions
diff --git a/Lua/src/base/USingScores.pas b/Lua/src/base/USingScores.pas index be0d4a58..56301539 100644 --- a/Lua/src/base/USingScores.pas +++ b/Lua/src/base/USingScores.pas @@ -138,9 +138,18 @@ type FirstPopUp: PScorePopUp; LastPopUp: PScorePopUp; + // only defined during draw, time passed between + // current and previous call of draw + TimePassed: Cardinal; + // draws a popup by pointer procedure DrawPopUp(const PopUp: PScorePopUp); + // raises players score if RaiseScore was called + // has to be called after DrawPopUp and before + // DrawScore + procedure DoRaiseScore(const Index: integer); + // draws a score by playerindex procedure DrawScore(const Index: integer); @@ -149,6 +158,10 @@ type // removes a popup w/o destroying the list procedure KillPopUp(const last, cur: PScorePopUp); + + // calculate the amount of points for a player that is + // still in popups and therfore not displayed + function GetPopUpPoints(const Index: integer): integer; public Settings: record // Record containing some Displaying Options Phase1Time: real; // time for phase 1 to complete (in msecs) @@ -202,6 +215,12 @@ type // it gives every player a score position procedure Init; + // raises the score of a specified player to the specified score + procedure RaiseScore(Player: byte; Score: integer); + + // sets the score of a specified player to the specified score + procedure SetScore(Player: byte; Score: integer); + // spawns a new line bonus popup for the player procedure SpawnPopUp(const PlayerIndex: byte; const Rating: integer; const Score: integer); @@ -216,6 +235,7 @@ implementation uses SysUtils, + Math, SDL, TextGL, ULog, @@ -319,6 +339,7 @@ procedure TSingScores.ClearPlayers; begin KillAllPopUps; oPlayerCount := 0; + TimePassed := 0; end; {** @@ -329,6 +350,7 @@ begin KillAllPopUps; oPlayerCount := 0; oPositionCount := 0; + TimePassed := 0; end; {** @@ -401,6 +423,30 @@ begin end; {** + * raises the score of a specified player to the specified score + *} +procedure TSingScores.RaiseScore(Player: byte; Score: integer); +begin + if (Player <= PlayerCount - 1) then + aPlayers[Player].Score := Score; +end; + +{** + * sets the score of a specified player to the specified score + *} +procedure TSingScores.SetScore(Player: byte; Score: integer); + var + Diff: Integer; +begin + if (Player <= PlayerCount - 1) then + begin + Diff := Score - Players[Player].Score; + aPlayers[Player].Score := Score; + Inc(aPlayers[Player].ScoreDisplayed, Diff); + end; +end; + +{** * spawns a new line bonus popup for the player *} procedure TSingScores.SpawnPopUp(const PlayerIndex: byte; const Rating: integer; const Score: integer); @@ -516,6 +562,32 @@ begin end; {** + * calculate the amount of points for a player that is + * still in popups and therfore not displayed + *} +function TSingScores.GetPopUpPoints(const Index: integer): integer; + var + CurPopUp: PScorePopUp; +begin + Result := 0; + + // only check points if there is a difference between actual + // and displayed points + if (Players[Index].Score > Players[Index].ScoreDisplayed) then + begin + CurPopUp := FirstPopUp; + while (CurPopUp <> nil) do + begin + if (CurPopUp.Player = Index) then + begin // add points left "in" popup to result + Inc(Result, CurPopUp.ScoreDiff - CurPopUp.ScoreGiven); + end; + CurPopUp := CurPopUp.Next; + end; + end; +end; + +{** * has to be called after positions and players have been added, before first call of draw * it gives each player a score position *} @@ -617,6 +689,8 @@ var CurPopUp, LastPopUp: PScorePopUp; begin CurTime := SDL_GetTicks; + if (TimePassed <> 0) then + TimePassed := CurTime - TimePassed; if Visible then begin @@ -647,6 +721,7 @@ begin // draw players w/ rating bar for I := 0 to PlayerCount-1 do begin + DoRaiseScore(I); DrawScore(I); DrawRatingBar(I); end @@ -654,10 +729,38 @@ begin // draw players w/o rating bar for I := 0 to PlayerCount-1 do begin + DoRaiseScore(I); DrawScore(I); end; end; // eo visible + + TimePassed := CurTime; +end; + +{** + * raises players score if RaiseScore was called + * has to be called after DrawPopUp and before + * DrawScore + *} +procedure TSingScores.DoRaiseScore(const Index: integer); + var + S: integer; + Diff: integer; + const + RaisePerSecond = 500; +begin + S := (Players[Index].Score - Players[Index].ScoreDisplayed) + GetPopUpPoints(Index); + + if (S <> 0) then + begin + if (S > 0) then + Diff := Min(Round(RoundTo((RaisePerSecond * TimePassed) / 1000, 1)), S) + else + Diff := Max(Round(RoundTo((RaisePerSecond * TimePassed) / 1000, 1)), S); + + Inc(aPlayers[Index].ScoreDisplayed, Diff); + end; end; {** diff --git a/Lua/src/base/USong.pas b/Lua/src/base/USong.pas index c465f198..fccf2757 100644 --- a/Lua/src/base/USong.pas +++ b/Lua/src/base/USong.pas @@ -96,7 +96,7 @@ type function ParseLyricStringParam(const Line: RawByteString; var LinePos: integer): RawByteString; function ParseLyricIntParam(const Line: RawByteString; var LinePos: integer): integer; - function ParseLyricFloatParam(const Line: RawByteString; var LinePos: integer): real; + function ParseLyricFloatParam(const Line: RawByteString; var LinePos: integer): extended; function ParseLyricCharParam(const Line: RawByteString; var LinePos: integer): AnsiChar; function ParseLyricText(const Line: RawByteString; var LinePos: integer): RawByteString; @@ -346,24 +346,26 @@ var begin OldLinePos := LinePos; Str := ParseLyricStringParam(Line, LinePos); - try - Result := StrToInt(Str); - except // on EConvertError + + if not TryStrToInt(Str, Result) then + begin // on convert error + Result := 0; LinePos := OldLinePos; raise EUSDXParseException.Create('Integer expected'); end; end; -function TSong.ParseLyricFloatParam(const Line: RawByteString; var LinePos: integer): real; +function TSong.ParseLyricFloatParam(const Line: RawByteString; var LinePos: integer): extended; var Str: RawByteString; OldLinePos: integer; begin OldLinePos := LinePos; Str := ParseLyricStringParam(Line, LinePos); - try - Result := StrToFloat(Str); - except // on EConvertError + + if not TryStrToFloat(Str, Result) then + begin // on convert error + Result := 0; LinePos := OldLinePos; raise EUSDXParseException.Create('Float expected'); end; @@ -378,6 +380,14 @@ begin Str := ParseLyricStringParam(Line, LinePos); if (Length(Str) <> 1) then begin + { to-do : decide what to do here + usdx < 1.1 does not nead a whitespace after a char param + so we may just write a warning to error.log and use the + first non whitespace character instead of raising an + exception that causes the song not to load. So the more + error resistant code is: + LinePos := OldLinePos + 1; + // raise EUSDXParseException.Create('Character expected'); } LinePos := OldLinePos; raise EUSDXParseException.Create('Character expected'); end; @@ -483,7 +493,7 @@ begin while true do begin - LinePos := 0; + LinePos := 1; Param0 := ParseLyricCharParam(CurLine, LinePos); if (Param0 = 'E') then diff --git a/Lua/src/screens/UScreenSing.pas b/Lua/src/screens/UScreenSing.pas index f907051c..18496517 100644 --- a/Lua/src/screens/UScreenSing.pas +++ b/Lua/src/screens/UScreenSing.pas @@ -1004,7 +1004,9 @@ begin // spawn rating pop-up Rating := Round(LinePerfection * MAX_LINE_RATING); Scores.SpawnPopUp(PlayerIndex, Rating, CurrentPlayer.ScoreTotalInt); - end; + end + else + Scores.RaiseScore(PlayerIndex, CurrentPlayer.ScoreTotalInt); // PerfectLineTwinkle (effect), part 1 if (Ini.EffectSing = 1) then |