--[[
* 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;