--[[ * UltraStar Deluxe - Karaoke Game * * UltraStar Deluxe is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/game/plugins/holdtheline.usdx $ * $Id: holdtheline.usdx 2258 2010-06-17 17:30:16Z b_krueger $ *]] --Configuration -- limit to get local startRatingLimit = 0; --percentage : from 0 to 1 , eg. 0.1 local fullRatingLimit = 1; --percentage : from 0 to 1 , eg. 0.95 local ratingLimit = startRatingLimit; -- percentage of the song-time, to need the full rating ( [start.beat + line.length] of the last line is the "end" of the song local percentageToFullRating = 0.75; --percentage : from 0 to 1 , eg. 0.75 -- position of big progress bar in the center local Indicator = {}; Indicator.Width = 10; --pixles Indicator.Height = 10; --pixles --Do not Change a Line if ya do not know what ya doing! -- scoring local scores = {}; local lastDissmissedNo; local dissmissedCount; function plugin_init() register('party mode: holdtheline', '0.6', 'USDX Team', 'http://www.UltrastarDeluxe.org'); require('math', 'Usdx.Party', 'Usdx.ScreenSing', 'Usdx.Gl', 'Usdx.TextGl'); local Mode = {} Mode.Name = 'holdtheline'; Mode.CanParty = true; Mode.PlayerCount = {1,2,3,4,5,6}; Mode.BeforeSing = 'BeforeSing' Mode.OnSing = 'Sing'; Mode.AfterSing = 'Finish'; Usdx.Party.Register(Mode); return true; end function BeforeSing() hSongLoaded = Usdx.Hook('ScreenSing.SongLoaded', 'Prepare'); hDraw = Usdx.Hook('Display.Draw', 'Draw'); return true; end; function Prepare() -- get beat-sum of the whole song local Lines = ScreenSing.GetSongLines(); local lastNote = Lines[#Lines].Notes[#Lines[#Lines].Notes]; TotalBeats = lastNote.Start + lastNote.Length; -- calculate OSD position for players do local RBRect = ScreenSing.GetRBRect(); OSD = {}; for i = 1, #RBRect do OSD[i] = {}; OSD[i].Left = RBRect[i].x; OSD[i].Right = RBRect[i].x + RBRect[i].w; OSD[i].Top = RBRect[i].y + RBRect[i].h; OSD[i].Bottom = RBRect[i].y + RBRect[i].h + math.max(RBRect[i].h, 13); scores[i] = false; end; end; --fill some Vars with values Teams = Party.GetTeams(); --team-infos lastDissmissedNo = 1; --dismissed-runner dissmissedCount = 0; --dismissed-counter -- remove hook hSongLoaded:Unhook(); hSongLoaded = nil; end; function DrawPlayerIndicator(i) Gl.Disable('GL_TEXTURE_2D'); local xOffset = ratingLimit * (OSD[i].Right - OSD[i].Left) -- background Gl.Color (0, 1, 0, 1); Gl.Begin('GL_QUADS'); Gl.Vertex(OSD[i].Left+xOffset-(Indicator.Width/2), OSD[i].Top+Indicator.Height); Gl.Vertex(OSD[i].Left+xOffset, OSD[i].Top); Gl.Vertex(OSD[i].Left+xOffset, OSD[i].Top); Gl.Vertex(OSD[i].Left+xOffset+(Indicator.Width/2), OSD[i].Top+Indicator.Height); Gl.End(); end; function DrawOut(i) Gl.Disable('GL_TEXTURE_2D'); local Text = ' OUT '; -- text Gl.Color(1, 0, 0, 1); TextGl.Size(18); TextGl.Style(1); TextGl.Italic(false); local PosX = (OSD[i].Left + OSD[i].Right) / 2; PosX = PosX - TextGl.Width(Text) / 2; TextGl.Pos(PosX, OSD[i].Top - 3); TextGl.Print(Text); end; function Finish() -- remove hook hDraw:Unhook(); --hDraw = nil; if dissmissedCount >= (#Teams-1) then --calculate scoring out of the dissmissed-order local Ranking = {}; for i = 1, #Teams do if (type(scores[i]) == "boolean") then Ranking[i] = 1; else Ranking[i] = #Teams - scores[i] + 1; end; end; Party.SetRoundRanking(Ranking); end; return (dissmissedCount < (#Teams-1)); end; function Draw() for i = 1, #Teams do if scores[i] == false then DrawPlayerIndicator(i); else --todo: draw dismissed-texture OVER the scoreing as a stamp or sth else DrawOut(i); end; end; end; function Sing() local Ratings = Usdx.ScreenSing.GetRating(); local finished = true; local dismissedAPlayer = false; -- calculate the x-offset of the indicator (ratingLimit) local currentBeat = ScreenSing.GetBeat(); if (currentBeat<0) then ratingLimit = startRatingLimit; elseif (currentBeat <= (TotalBeats*percentageToFullRating)) then ratingLimit = ((fullRatingLimit-startRatingLimit) / (TotalBeats*percentageToFullRating)) * currentBeat + startRatingLimit; else ratingLimit = fullRatingLimit; end; for i = 1, #Teams do if scores[i] == false then --player no. i is still in game if Ratings[i] >= ratingLimit then finished = false; else --todo: play dismissed-sound --todo: disable player i (bars from player i) dismissedAPlayer = true; dissmissedCount = dissmissedCount + 1; scores[i] = lastDissmissedNo; end; end; end; --if more than one player is dismissed in one round, --this guarantees correct scoring if dismissedAPlayer == true then lastDissmissedNo = lastDissmissedNo + 1; end; --if only one player is in game, this round is finished if dissmissedCount >= (#Teams-1) then ScreenSing.Finish(); end; end;