aboutsummaryrefslogtreecommitdiffstats
path: root/game/plugins/holdtheline.usdx
blob: 85a57d215d50425cbbebf9b758c002720609029e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
--[[
 * 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;