Xonotic
mapvoting.qc
Go to the documentation of this file.
1 #include "mapvoting.qh"
2 
3 #include <client/draw.qh>
4 #include <client/hud/_mod.qh>
6 #include <common/mapinfo.qh>
7 #include <common/util.qh>
8 
9 // MapVote (#21)
10 
11 void MapVote_Draw_Export(int fh)
12 {
13  // allow saving cvars that aesthetically change the panel into hud skin files
14  HUD_Write_Cvar("hud_panel_mapvote_highlight_border");
15 }
16 
18 
19 string mv_maps[MAPVOTE_COUNT];
20 string mv_pics[MAPVOTE_COUNT];
21 string mv_pk3[MAPVOTE_COUNT]; // map pk3 name or gametype human readable name
22 string mv_desc[MAPVOTE_COUNT];
23 float mv_preview[MAPVOTE_COUNT];
24 float mv_votes[MAPVOTE_COUNT];
25 float mv_flags[MAPVOTE_COUNT];
26 float mv_flags_start[MAPVOTE_COUNT];
28 float mv_abstain;
29 float mv_ownvote;
30 float mv_detail;
31 float mv_timeout;
34 
39 
44 
45 const int NUM_SSDIRS = 4;
48 
49 bool PreviewExists(string name)
50 {
52  return false;
53 
54  if (fexists(strcat(name, ".tga"))) return true;
55  if (fexists(strcat(name, ".png"))) return true;
56  if (fexists(strcat(name, ".jpg"))) return true;
57  if (fexists(strcat(name, ".pcx"))) return true;
58 
59  return false;
60 }
61 
62 string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, vector fontsize)
63 {
64  TC(int, id);
65  string pre, post;
66  pre = sprintf("%d. ", id+1);
67  if(mv_detail)
68  {
69  if(_count == 1)
70  post = _(" (1 vote)");
71  else if(_count >= 0 && (mv_flags[id] & GTV_AVAILABLE))
72  post = sprintf(_(" (%d votes)"), _count);
73  else
74  post = "";
75  }
76  else
77  post = "";
78  maxwidth -= stringwidth(pre, false, fontsize) + stringwidth(post, false, fontsize);
79  map = textShortenToWidth(map, maxwidth, fontsize, stringwidth_nocolors);
80  return strcat(pre, map, post);
81 }
82 
84 {
85  TC(int, id);
86  if(!(mv_flags[id] & GTV_AVAILABLE))
87  return '1 1 1';
88  if(id == mv_ownvote)
89  return '0 1 0';
90  else if (id == mv_selection)
91  return '1 1 0';
92  else
93  return '1 1 1';
94 }
95 
96 void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float _count, int id)
97 {
98  TC(int, id);
99  // Find the correct alpha
100  float alpha;
101  if(!(mv_flags_start[id] & GTV_AVAILABLE))
102  alpha = 0.2; // The gametype isn't supported by the map
103  else if ( !(mv_flags[id] & GTV_AVAILABLE) && mv_top2_alpha)
104  alpha = mv_top2_alpha; // Fade away if not one of the top 2 choice
105  else
106  alpha = 1; // Normal, full alpha
107  alpha *= panel_fg_alpha;
108 
109  // Bounding box details
110  float rect_margin = hud_fontsize.y / 2;
111 
112  pos.x += rect_margin + autocvar_hud_panel_mapvote_highlight_border;
113  pos.y += rect_margin + autocvar_hud_panel_mapvote_highlight_border;
114  maxh -= 2 * (rect_margin + autocvar_hud_panel_mapvote_highlight_border);
115  tsize -= 2 * (rect_margin + autocvar_hud_panel_mapvote_highlight_border);
116 
117  vector rect_pos = pos - '0.5 0.5 0' * rect_margin;
118  vector rect_size = '1 1 0';
119  rect_size.x = tsize + rect_margin;
120  rect_size.y = maxh + rect_margin;
121 
122  // Highlight selected item
123  if(id == mv_selection && (mv_flags[id] & GTV_AVAILABLE))
124  {
125  drawfill(rect_pos, rect_size, '1 1 1', 0.1 * panel_fg_alpha, DRAWFLAG_NORMAL);
126  }
127 
128  // Highlight current vote
129  vector rgb = MapVote_RGB(id);
130  if(id == mv_ownvote)
131  {
132  drawfill(rect_pos, rect_size, rgb, 0.1 * alpha, DRAWFLAG_NORMAL);
133  drawborderlines(autocvar_hud_panel_mapvote_highlight_border, rect_pos, rect_size, rgb, alpha, DRAWFLAG_NORMAL);
134  }
135 
136  vector offset = pos;
137 
138  float title_gap = gtv_text_size.y * 1.4; // distance between the title and the description
139  pos.y += title_gap;
140  maxh -= title_gap;
141 
142  // Evaluate the image size
143  vector image_size = '1 1 0' * gtv_text_size.x * 3;
144  if ( maxh < image_size.y )
145  image_size = '1 1 0' * maxh;
146  image_size *= 0.8;
147  float desc_padding = gtv_text_size.x * 0.6;
148  pos.x += image_size.x + desc_padding;
149  tsize -= image_size.x + desc_padding;
150 
151  // Split the description into lines
152  entity title;
153  title = spawn();
154  title.message = MapVote_FormatMapItem(id, mv_pk3[id], _count, tsize, gtv_text_size);
155 
156  string thelabel = mv_desc[id], ts;
157  entity last = title;
158  entity next = NULL;
159  float nlines = 0;
160  if( thelabel != "")
161  {
162  float i,n = tokenizebyseparator(thelabel, "\n");
163  for(i = 0; i < n && maxh > (nlines+1)*gtv_text_size_small.y; ++i)
164  {
166  while(getWrappedLine_remaining && maxh > (nlines+1)*gtv_text_size_small.y)
167  {
168  ts = getWrappedLine(tsize, gtv_text_size_small, stringwidth_colors);
169  if (ts != "")
170  {
171  next = spawn();
172  next.message = ts;
173  next.origin = pos-offset;
174  last.chain = next;
175  last = next;
176  pos.y += gtv_text_size_small.y;
177  nlines++;
178  }
179  }
180  }
181  }
182 
183  // Center the contents in the bounding box
184  maxh -= max(nlines*gtv_text_size_small.y,image_size.y);
185  if ( maxh > 0 )
186  offset.y += maxh/2;
187 
188  // Draw the title
189  drawstring(offset, title.message, gtv_text_size, rgb, alpha, DRAWFLAG_NORMAL);
190 
191  // Draw the icon
192  if(pic != "")
193  drawpic('0 1 0'*title_gap+'0.5 0 0'*desc_padding+offset, pic, image_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
194 
195  // Draw the description
196  for ( last = title.chain; last ; )
197  {
198  drawstring(last.origin+offset, last.message, gtv_text_size_small, '1 1 1', alpha, DRAWFLAG_NORMAL);
199  next = last;
200  last = last.chain;
201  delete(next);
202  }
203 
204  // Cleanup
205  delete(title);
206 }
207 
208 void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, string pic, float _count, int id)
209 {
210  TC(int, id);
211  vector img_size = '0 0 0';
212  string label;
213  float text_size;
214 
215  float rect_margin = hud_fontsize.y / 2;
216 
217  pos.x += rect_margin + autocvar_hud_panel_mapvote_highlight_border;
218  pos.y += rect_margin + autocvar_hud_panel_mapvote_highlight_border;
219  isize -= 2 * (rect_margin + autocvar_hud_panel_mapvote_highlight_border);
220  tsize -= 2 * (rect_margin + autocvar_hud_panel_mapvote_highlight_border);
221 
222  vector rect_pos = pos - '0.5 0.5 0' * rect_margin;
223  vector rect_size = '1 1 0';
224  rect_size.x = tsize + rect_margin;
225  rect_size.y = isize + rect_margin;
226 
227  float img_ar = 4/3;
228  img_size.x = min(tsize, isize * img_ar);
229  img_size.y = img_size.x / img_ar;
230  img_size.y -= hud_fontsize.y;
231  img_size.x = img_size.y * img_ar;
232 
233  pos.y += (isize - img_size.y - hud_fontsize.y) / 2;
234 
235  label = MapVote_FormatMapItem(id, map, _count, tsize, hud_fontsize);
236 
237  text_size = stringwidth(label, false, hud_fontsize);
238 
239  float save_rect_sizex = rect_size.x;
240  rect_size.x = max(img_size.x, text_size) + rect_margin;
241  rect_pos.x += (save_rect_sizex - rect_size.x) / 2;
242 
243  vector text_pos = '0 0 0';
244  text_pos.x = pos.x + (tsize - text_size) / 2;
245  text_pos.y = pos.y + img_size.y;
246 
247  pos.x += (tsize - img_size.x) / 2;
248 
249  float theAlpha;
250  if (!(mv_flags[id] & GTV_AVAILABLE) && mv_top2_alpha)
251  theAlpha = mv_top2_alpha;
252  else
253  theAlpha = 1;
254  theAlpha *= panel_fg_alpha;
255 
256  // Highlight selected item
257  if(id == mv_selection && (mv_flags[id] & GTV_AVAILABLE))
258  drawfill(rect_pos, rect_size, '1 1 1', 0.1 * panel_fg_alpha, DRAWFLAG_NORMAL);
259 
260  // Highlight current vote
261  vector rgb = MapVote_RGB(id);
262  if(id == mv_ownvote)
263  {
264  drawfill(rect_pos, rect_size, rgb, 0.1 * theAlpha, DRAWFLAG_NORMAL);
265  drawborderlines(autocvar_hud_panel_mapvote_highlight_border, rect_pos, rect_size, rgb, theAlpha, DRAWFLAG_NORMAL);
266  }
267 
268  drawstring(text_pos, label, hud_fontsize, rgb, theAlpha, DRAWFLAG_NORMAL);
269 
270  if(pic == "")
271  {
272  drawfill(pos, img_size, '.5 .5 .5', .7 * theAlpha, DRAWFLAG_NORMAL);
273  }
274  else
275  {
276  if(drawgetimagesize(pic) == '0 0 0')
277  drawpic(pos, draw_UseSkinFor("nopreview_map"), img_size, '1 1 1', theAlpha, DRAWFLAG_NORMAL);
278  else
279  drawpic(pos, pic, img_size, '1 1 1', theAlpha, DRAWFLAG_NORMAL);
280  }
281 }
282 
283 void MapVote_DrawAbstain(vector pos, float isize, float tsize, float _count, int id)
284 {
285  TC(int, id);
286  vector rgb;
287  float text_size;
288  string label;
289 
290  rgb = MapVote_RGB(id);
291 
292  label = MapVote_FormatMapItem(id, _("Don't care"), _count, tsize, hud_fontsize);
293 
294  text_size = stringwidth(label, false, hud_fontsize);
295 
296  pos.x -= text_size*0.5;
298 }
299 
300 vector MapVote_GridVec(vector gridspec, int i, int m)
301 {
302  TC(int, i); TC(int, m);
303  int r = i % m;
304  return
305  '1 0 0' * (gridspec.x * r)
306  +
307  '0 1 0' * (gridspec.y * (i - r) / m);
308 }
309 
310 float MapVote_Selection(vector topleft, vector cellsize, float rows, float columns)
311 {
312 
313  float c, r;
314 
315  mv_mouse_selection = -1;
316 
317  for (r = 0; r < rows; ++r)
318  for (c = 0; c < columns; ++c)
319  {
320  if (mousepos.x >= topleft.x + cellsize.x * c &&
321  mousepos.x <= topleft.x + cellsize.x * (c + 1) &&
322  mousepos.y >= topleft.y + cellsize.y * r &&
323  mousepos.y <= topleft.y + cellsize.y * (r + 1))
324  {
325  mv_mouse_selection = r * columns + c;
326  break;
327  }
328  }
329 
331  mv_mouse_selection = -1;
332 
333  if (mv_abstain && mv_mouse_selection < 0)
335 
336  if ( mv_selection_keyboard )
337  return mv_selection;
338 
339  return mv_mouse_selection;
340 }
341 
342 // draws map vote or gametype vote
344 {
345  string map;
346  int i;
347  float tmp;
348  vector pos;
349  float center;
350  float rows;
351  vector dist = '0 0 0';
352 
353  //if(intermission != 2) return;
354  if(!mv_active)
355  return;
356 
358 
359  center = (vid_conwidth - 1)/2;
360  xmin = vid_conwidth * 0.08;
361  xmax = vid_conwidth - xmin;
362  ymin = 20;
363  ymax = vid_conheight - ymin;
364 
365  if(chat_posy + chat_sizey / 2 < vid_conheight / 2)
366  ymin += chat_sizey;
367  else
368  ymax -= chat_sizey;
369 
370  hud_fontsize = HUD_GetFontsize("hud_fontsize");
371  if (gametypevote)
372  {
373  gtv_text_size = hud_fontsize * 1.4;
375  }
376 
377  pos.y = ymin;
378  pos.z = 0;
379 
382 
383  map = ((gametypevote) ? _("Decide the gametype") : _("Vote for a map"));
384  pos.x = center - stringwidth(map, false, hud_fontsize * 2) * 0.5;
385  drawstring(pos, map, hud_fontsize * 2, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
386  pos.y += hud_fontsize.y * 2;
387 
388  if( mapvote_chosenmap != "" )
389  {
390  pos.y += hud_fontsize.y * 0.25;
391  pos.x = center - stringwidth(mapvote_chosenmap, false, hud_fontsize * 1.5) * 0.5;
393  pos.y += hud_fontsize.y * 1.5;
394  }
395  pos.y += hud_fontsize.y * 0.5;
396 
398 
399  i = ceil(max(0, mv_timeout - time));
400  map = sprintf(_("%d seconds left"), i);
401  pos.x = center - stringwidth(map, false, hud_fontsize * 1.5) * 0.5;
402  drawstring(pos, map, hud_fontsize * 1.5, '0 1 0', panel_fg_alpha, DRAWFLAG_NORMAL);
403  pos.y += hud_fontsize.y * 1.5;
404  pos.y += hud_fontsize.y * 0.5;
405 
406  // base for multi-column stuff...
407  pos.y += hud_fontsize.y;
408  pos.x = xmin;
409  ymin = pos.y;
410  float abstain_spacing = panel_bg_border + hud_fontsize.y;
411  if(mv_abstain)
412  {
413  mv_num_maps -= 1;
414  ymax -= abstain_spacing;
415  }
416 
417  // higher than the image itself ratio for mapvote items to reserve space for long map names
418  int item_aspect = (gametypevote) ? 3/1 : 5/3;
419  vector table_size = HUD_GetTableSize_BestItemAR(mv_num_maps, vec2(xmax - xmin, ymax - ymin), item_aspect);
420  mv_columns = table_size.x;
421  rows = table_size.y;
422 
423  dist.x = (xmax - xmin) / mv_columns;
424  dist.y = (ymax - pos.y) / rows;
425 
426  // reduce size of too wide items
427  tmp = vid_conwidth / 3; // max width
428  if(dist.x > tmp)
429  {
430  dist.x = tmp;
431  dist.y = min(dist.y, dist.x / item_aspect);
432  }
433  tmp = vid_conheight / 3; // max height
434  if(dist.y > tmp)
435  {
436  dist.y = tmp;
437  dist.x = min(dist.x, dist.y * item_aspect);
438  }
439 
440  // reduce size to fix aspect ratio
441  if(dist.x / dist.y > item_aspect)
442  dist.x = dist.y * item_aspect;
443  else
444  dist.y = dist.x / item_aspect;
445 
446  // adjust table pos and size according to the new size
447  float offset;
448  offset = ((xmax - pos.x) - dist.x * mv_columns) / 2;
449  xmin = pos.x += offset;
450  xmax -= offset;
451  offset = ((ymax - pos.y) - dist.y * rows) / 2;
452  ymax -= 2 * offset;
453 
454  // override panel_pos and panel_size
455  panel_pos.x = pos.x;
456  panel_pos.y = pos.y;
457  panel_size.x = xmax - xmin;
458  panel_size.y = ymax - ymin;
460 
461  if(panel_bg_padding)
462  {
463  // FIXME item AR gets slightly changed here...
464  // it's rather hard to avoid it at this point
465  dist.x -= 2 * panel_bg_padding / mv_columns;
466  dist.y -= 2 * panel_bg_padding / rows;
467  xmin = pos.x += panel_bg_padding;
468  ymin = pos.y += panel_bg_padding;
469  xmax -= 2 * panel_bg_padding;
470  ymax -= 2 * panel_bg_padding;
471  }
472 
473  mv_selection = MapVote_Selection(pos, dist, rows, mv_columns);
474 
475  if (mv_top2_time)
476  mv_top2_alpha = max(0.2, 1 - (time - mv_top2_time) ** 2);
477 
478  void (vector, float, float, string, string, float, float) DrawItem;
479 
480  if(gametypevote)
482  else
483  DrawItem = MapVote_DrawMapItem;
484 
485  for(i = 0; i < mv_num_maps; ++i)
486  {
487  tmp = mv_votes[i]; // FTEQCC bug: too many array accesses in the function call screw it up
488  map = mv_maps[i];
489  if(mv_preview[i])
490  DrawItem(pos + MapVote_GridVec(dist, i, mv_columns), dist.y, dist.x, map, mv_pics[i], tmp, i);
491  else
492  DrawItem(pos + MapVote_GridVec(dist, i, mv_columns), dist.y, dist.x, map, "", tmp, i);
493  }
494 
495  if(mv_abstain)
496  ++mv_num_maps;
497 
498  if(mv_abstain && i < mv_num_maps) {
499  tmp = mv_votes[i];
500  pos.y = ymax + abstain_spacing;
501  pos.x = (xmax+xmin)*0.5;
502  MapVote_DrawAbstain(pos, dist.x, xmax - xmin, tmp, i);
503  }
504 }
505 
507 {
508  TC(int, argc);
509  entity pak;
510 
511  if(argc != 2 || !mv_pk3list)
512  {
513  LOG_INFO(_("mv_mapdownload: ^3You're not supposed to use this command on your own!"));
514  return;
515  }
516 
517  int id = stof(argv(1));
518  for(pak = mv_pk3list; pak; pak = pak.chain)
519  if(pak.sv_entnum == id)
520  break;
521 
522  if(!pak || pak.sv_entnum != id) {
523  LOG_INFO(_("^1Error:^7 Couldn't find pak index."));
524  return;
525  }
526 
527  if(PreviewExists(pak.message))
528  {
529  mv_preview[id] = true;
530  return;
531  } else {
532  LOG_INFO(_("Requesting preview..."));
533  localcmd(strcat("\ncmd mv_getpicture ", ftos(id), "\n"));
534  }
535 }
536 
537 void MapVote_CheckPK3(string pic, string pk3, int id)
538 {
539  TC(int, id);
540  entity pak;
541  pak = spawn();
542  pak.netname = pk3;
543  pak.message = pic;
544  pak.sv_entnum = id;
545 
546  pak.chain = mv_pk3list;
547  mv_pk3list = pak;
548 
549  if(pk3 != "")
550  {
551  localcmd(strcat("\ncurl --pak ", pk3, "; wait; cl_cmd mv_download ", ftos(id), "\n"));
552  }
553  else
554  {
555  Cmd_MapVote_MapDownload(tokenize_console(strcat("mv_download ", ftos(id))));
556  }
557 }
558 
559 void MapVote_CheckPic(string pic, string pk3, int id)
560 {
561  TC(int, id);
562  // never try to retrieve a pic for the "don't care" 'map'
563  if(mv_abstain && id == mv_num_maps - 1)
564  return;
565 
566  if(PreviewExists(pic))
567  {
568  mv_preview[id] = true;
569  return;
570  }
571  MapVote_CheckPK3(pic, pk3, id);
572 }
573 
575 {
576  int i;
577  if ( mv_num_maps < 24 )
578  {
579  int mask;
580  if(mv_num_maps < 8)
581  mask = ReadByte();
582  else if(mv_num_maps < 16)
583  mask = ReadShort();
584  else
585  mask = ReadLong();
586 
587  for(i = 0; i < mv_num_maps; ++i)
588  {
589  if (mask & BIT(i))
590  mv_flags[i] |= GTV_AVAILABLE;
591  else
592  mv_flags[i] &= ~GTV_AVAILABLE;
593  }
594  }
595  else
596  {
597  for(i = 0; i < mv_num_maps; ++i )
598  mv_flags[i] = ReadByte();
599  }
600 }
601 
603 {
604  TC(int, i);
605  string map = strzone(ReadString());
606  string pk3 = strzone(ReadString());
607  int j = bound(0, ReadByte(), n_ssdirs - 1);
608 
609  mv_maps[i] = map;
610  mv_pk3[i] = pk3;
611  mv_flags[i] = GTV_AVAILABLE;
612 
613  string pic = strzone(strcat(ssdirs[j], "/", map));
614  mv_pics[i] = pic;
615  mv_preview[i] = false;
616  MapVote_CheckPic(pic, pk3, i);
617 }
618 
620 {
621  TC(int, i);
622  string gt = strzone(ReadString());
623 
624  mv_maps[i] = gt;
625  mv_flags[i] = ReadByte();
626 
627  string basetype = "";
628 
629  if ( mv_flags[i] & GTV_CUSTOM )
630  {
631  string name = ReadString();
632  if ( strlen(name) < 1 )
633  name = gt;
634  mv_pk3[i] = strzone(name);
635  mv_desc[i] = strzone(ReadString());
636  basetype = strzone(ReadString());
637  }
638  else
639  {
640  Gametype type = MapInfo_Type_FromString(gt, false);
641  mv_pk3[i] = strzone(MapInfo_Type_ToText(type));
643  }
644 
645  string mv_picpath = sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, gt);
646  if(precache_pic(mv_picpath) == "")
647  {
648  mv_picpath = strcat("gfx/menu/default/gametype_", gt);
649  if(precache_pic(mv_picpath) == "")
650  {
651  mv_picpath = sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, basetype);
652  if(precache_pic(mv_picpath) == "")
653  {
654  mv_picpath = strcat("gfx/menu/default/gametype_", basetype);
655  }
656  }
657  }
658  string pic = strzone(mv_picpath);
659  mv_pics[i] = pic;
660  mv_preview[i] = PreviewExists(pic);
661 }
662 
664 {
665  mv_active = 1;
666  if(!autocvar_hud_cursormode) mousepos = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
667  mv_selection = -1;
669 
670  string s;
671  for(n_ssdirs = 0; ; ++n_ssdirs)
672  {
673  s = ReadString();
674  if(s == "")
675  break;
676  if(n_ssdirs < NUM_SSDIRS)
677  ssdirs[n_ssdirs] = s;
678  }
680 
681  mv_num_maps = min(MAPVOTE_COUNT, ReadByte());
682  mv_abstain = ReadByte();
683  if(mv_abstain)
684  mv_abstain = 1; // must be 1 for bool-true, makes stuff easier
685  mv_detail = ReadByte();
686 
687  mv_ownvote = -1;
688  mv_timeout = ReadCoord();
689 
690  gametypevote = ReadByte();
691 
692  if(gametypevote)
693  {
695  if ( gametypevote == 2 )
696  gametypevote = 0;
697  }
698 
700  int i;
701  for(i = 0; i < mv_num_maps; ++i )
702  mv_flags_start[i] = mv_flags[i];
703 
704  // Assume mv_pk3list is NULL, there should only be 1 mapvote per round
705  mv_pk3list = NULL; // I'm still paranoid!
706 
707  for(i = 0; i < mv_num_maps; ++i)
708  {
709  mv_votes[i] = 0;
710 
711  if ( gametypevote )
713  else
715  }
716 
717  for(i = 0; i < n_ssdirs; ++i)
718  ssdirs[n_ssdirs] = string_null;
719  n_ssdirs = 0;
720 }
721 
722 void MapVote_SendChoice(int index)
723 {
724  TC(int, index);
725  localcmd(strcat("\nimpulse ", ftos(index+1), "\n"));
726 }
727 
728 int MapVote_MoveLeft(int pos)
729 {
730  TC(int, pos);
731  int imp;
732  if ( pos < 0 )
733  imp = mv_num_maps - 1;
734  else
735  imp = pos < 1 ? mv_num_maps - 1 : pos - 1;
736  if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
737  imp = MapVote_MoveLeft(imp);
738  return imp;
739 }
740 int MapVote_MoveRight(int pos)
741 {
742  TC(int, pos);
743  int imp;
744  if ( pos < 0 )
745  imp = 0;
746  else
747  imp = pos >= mv_num_maps - 1 ? 0 : pos + 1;
748  if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
749  imp = MapVote_MoveRight(imp);
750  return imp;
751 }
752 int MapVote_MoveUp(int pos)
753 {
754  TC(int, pos);
755  int imp;
756  if ( pos < 0 )
757  imp = mv_num_maps - 1;
758  else
759  {
760  imp = pos - mv_columns;
761  if ( imp < 0 )
762  {
763  int mv_rows = ceil(mv_num_maps / mv_columns);
764  if (imp == -mv_columns) // pos == 0
765  imp = mv_columns * mv_rows - 1;
766  else
767  imp = imp + mv_columns * mv_rows - 1;
768  }
769  }
770  if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
771  imp = MapVote_MoveUp(imp);
772  return imp;
773 }
774 int MapVote_MoveDown(int pos)
775 {
776  TC(int, pos);
777  int imp;
778  if ( pos < 0 )
779  imp = 0;
780  else
781  {
782  imp = pos + mv_columns;
783  if ( imp >= mv_num_maps )
784  {
785  if ((imp % mv_columns) == mv_columns - 1)
786  imp = 0;
787  else
788  imp = imp % mv_columns + 1;
789  }
790  }
791  if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
792  imp = MapVote_MoveDown(imp);
793  return imp;
794 }
795 
796 float MapVote_InputEvent(int bInputType, float nPrimary, float nSecondary)
797 {
798  TC(int, bInputType);
799 
800  static int first_digit = 0;
801  if (!mv_active)
802  return false;
803 
804  if(bInputType == 3)
805  {
806  mousepos.x = nPrimary;
807  mousepos.y = nSecondary;
809  return true;
810  }
811 
812  if (bInputType == 2)
813  {
815  return false;
816  }
817 
818  // at this point bInputType can only be 0 or 1 (key pressed or released)
819  bool key_pressed = (bInputType == 0);
820 
821  if (key_pressed)
822  {
823  if (nPrimary == K_ALT) hudShiftState |= S_ALT;
824  if (nPrimary == K_CTRL) hudShiftState |= S_CTRL;
825  if (nPrimary == K_SHIFT) hudShiftState |= S_SHIFT;
826  }
827  else
828  {
829  if (nPrimary == K_ALT) hudShiftState -= (hudShiftState & S_ALT);
830  if (nPrimary == K_CTRL) hudShiftState -= (hudShiftState & S_CTRL);
831  if (nPrimary == K_SHIFT) hudShiftState -= (hudShiftState & S_SHIFT);
832 
833  if (nPrimary == K_CTRL)
834  first_digit = 0;
835  }
836 
837  int imp = 0;
838  switch(nPrimary)
839  {
840  case K_RIGHTARROW:
841  if (!key_pressed) return true;
844  return true;
845  case K_LEFTARROW:
846  if (!key_pressed) return true;
849  return true;
850  case K_DOWNARROW:
851  if (!key_pressed) return true;
854  return true;
855  case K_UPARROW:
856  if (!key_pressed) return true;
859  return true;
860  case K_KP_ENTER:
861  case K_ENTER:
862  case K_SPACE:
863  if (!key_pressed) return true;
864  if ( mv_selection_keyboard )
866  return true;
867  case '1': case K_KP_1: imp = 1; break;
868  case '2': case K_KP_2: imp = 2; break;
869  case '3': case K_KP_3: imp = 3; break;
870  case '4': case K_KP_4: imp = 4; break;
871  case '5': case K_KP_5: imp = 5; break;
872  case '6': case K_KP_6: imp = 6; break;
873  case '7': case K_KP_7: imp = 7; break;
874  case '8': case K_KP_8: imp = 8; break;
875  case '9': case K_KP_9: imp = 9; break;
876  case '0': case K_KP_0: imp = 10; break;
877  }
878 
879  if (imp && hudShiftState & S_CTRL)
880  {
881  if (!first_digit)
882  {
883  if (!key_pressed)
884  return true;
885  first_digit = imp % 10;
886  return true;
887  }
888  else
889  imp = first_digit * 10 + (imp % 10);
890  }
891 
892  if (nPrimary == K_MOUSE1)
893  {
894  if (!key_pressed)
895  return true;
898  if (mv_selection >= 0)
899  imp = min(mv_selection + 1, mv_num_maps);
900  }
901 
902  if (nPrimary == K_MOUSE2)
903  return true; // do nothing
904 
905  if (imp)
906  {
907  if (!key_pressed)
908  return true;
909  if (imp <= mv_num_maps)
910  localcmd(strcat("\nimpulse ", ftos(imp), "\n"));
911  return true;
912  }
913 
914  return false;
915 }
916 
918 {
920  mv_top2_time = time;
921 }
922 
924 {
925  int i;
926  for(i = 0; i < mv_num_maps; ++i)
927  {
928  if(mv_flags[i] & GTV_AVAILABLE)
929  {
930  if(mv_detail)
931  mv_votes[i] = ReadByte();
932  else
933  mv_votes[i] = 0;
934  }
935  else
936  mv_votes[i] = -1;
937  }
938 
939  mv_ownvote = ReadByte()-1;
940 }
941 
942 NET_HANDLE(ENT_CLIENT_MAPVOTE, bool isnew)
943 {
944  make_pure(this);
945  int sf = ReadByte();
946  return = true;
947 
948  if(sf & 1)
949  MapVote_Init();
950 
951  if(sf & 2)
953 
954  if(sf & 4)
956 }
957 
958 NET_HANDLE(TE_CSQC_PICTURE, bool isNew)
959 {
961  return true;
962 }
963 
965 {
966  int type = ReadByte();
967  mv_preview[type] = true;
968  mv_pics[type] = strzone(ReadPicture());
969 }
int mv_num_maps
Definition: mapvoting.qc:17
string mv_maps[MAPVOTE_COUNT]
Definition: mapvoting.qc:19
int int int imp
Definition: impulse.qc:90
float vid_conheight
float K_UPARROW
Definition: keycodes.qc:15
float panel_bg_border
Definition: hud.qh:169
float K_ALT
Definition: keycodes.qc:20
#define draw_endBoldFont()
Definition: draw.qh:5
float alpha
Definition: items.qc:14
float panel_fg_alpha
Definition: hud.qh:166
string string_null
Definition: nil.qh:9
int n_ssdirs
Definition: mapvoting.qc:47
string ssdirs[NUM_SSDIRS]
Definition: mapvoting.qc:46
string getWrappedLine_remaining
Definition: util.qh:108
void MapVote_CheckPK3(string pic, string pk3, int id)
Definition: mapvoting.qc:537
void MapVote_UpdateMask()
Definition: mapvoting.qc:917
void MapVote_Draw()
Definition: mapvoting.qc:343
#define ReadString
string mapvote_chosenmap
Definition: mapvoting.qc:41
int MapVote_MoveDown(int pos)
Definition: mapvoting.qc:774
float K_KP_1
Definition: keycodes.qc:50
float K_DOWNARROW
Definition: keycodes.qc:16
entity mv_pk3list
Definition: mapvoting.qc:27
#define stringwidth
Definition: csprogsdefs.qh:29
float K_KP_7
Definition: keycodes.qc:61
#define draw_beginBoldFont()
Definition: draw.qh:4
int MapVote_MoveUp(int pos)
Definition: mapvoting.qc:752
const int S_SHIFT
Definition: hud.qh:127
float mv_flags_start[MAPVOTE_COUNT]
Definition: mapvoting.qc:26
vector panel_size
Definition: hud.qh:160
entity() spawn
float xmin
Definition: mapvoting.qh:20
const int NUM_SSDIRS
Definition: mapvoting.qc:45
float chat_sizey
Definition: hud.qh:180
string MapInfo_Type_ToText(Gametype t)
Definition: mapinfo.qc:621
float K_KP_3
Definition: keycodes.qc:54
vector HUD_GetTableSize_BestItemAR(int item_count, vector psize, float item_aspect)
Definition: hud.qc:172
void HUD_Scale_Disable()
Definition: hud.qc:83
string textShortenToWidth(string theText, float maxWidth, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
Definition: util.qc:956
int MapVote_MoveRight(int pos)
Definition: mapvoting.qc:740
float K_KP_4
Definition: keycodes.qc:56
int mv_selection
Definition: mapvoting.qc:35
void MapVote_CheckPic(string pic, string pk3, int id)
Definition: mapvoting.qc:559
float vid_conwidth
float K_SHIFT
Definition: keycodes.qc:22
float mv_active
Definition: mapvoting.qh:19
vector gtv_text_size
Definition: mapvoting.qc:42
float K_SPACE
Definition: keycodes.qc:10
float K_RIGHTARROW
Definition: keycodes.qc:18
vector drawgetimagesize(string pic)
bool autocvar_cl_readpicture_force
Definition: mapvoting.qh:5
int MapVote_MoveLeft(int pos)
Definition: mapvoting.qc:728
const int S_ALT
Definition: hud.qh:129
vector MapVote_GridVec(vector gridspec, int i, int m)
Definition: mapvoting.qc:300
void MapVote_ReadOption(int i)
Definition: mapvoting.qc:602
string draw_UseSkinFor(string pic)
Definition: util.qc:206
float K_KP_ENTER
Definition: keycodes.qc:74
float autocvar_hud_panel_mapvote_highlight_border
Definition: mapvoting.qh:6
float mv_top2_time
Definition: mapvoting.qc:32
vector MapVote_RGB(int id)
Definition: mapvoting.qc:83
float mv_ownvote
Definition: mapvoting.qc:29
#define HUD_Panel_DrawBg()
Definition: hud.qh:54
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
vector gtv_text_size_small
Definition: mapvoting.qc:43
Gametype MapInfo_Type_FromString(string gtype, bool dowarn)
Definition: mapinfo.qc:589
void Net_MapVote_Picture()
Definition: mapvoting.qc:964
int hudShiftState
Definition: hud.qh:126
int mv_selection_keyboard
Definition: mapvoting.qc:38
float MapVote_InputEvent(int bInputType, float nPrimary, float nSecondary)
Definition: mapvoting.qc:796
float chat_posy
Definition: hud.qh:179
void MapVote_DrawAbstain(vector pos, float isize, float tsize, float _count, int id)
Definition: mapvoting.qc:283
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
vector HUD_GetFontsize(string cvarname)
Definition: hud.qc:111
string mv_desc[MAPVOTE_COUNT]
Definition: mapvoting.qc:22
float K_KP_9
Definition: keycodes.qc:65
float K_KP_2
Definition: keycodes.qc:52
float mv_preview[MAPVOTE_COUNT]
Definition: mapvoting.qc:23
float K_CTRL
Definition: keycodes.qc:21
float K_MOUSE2
Definition: keycodes.qc:130
string autocvar_menu_skin
Definition: mapvoting.qh:7
#define NULL
Definition: post.qh:17
#define LOG_INFO(...)
Definition: log.qh:70
float mv_flags[MAPVOTE_COUNT]
Definition: mapvoting.qc:25
const float DRAWFLAG_NORMAL
Definition: csprogsdefs.qc:317
float mv_abstain
Definition: mapvoting.qc:28
#define TC(T, sym)
Definition: _all.inc:82
float K_KP_8
Definition: keycodes.qc:63
string mv_pics[MAPVOTE_COUNT]
Definition: mapvoting.qc:20
vector panel_pos
Definition: hud.qh:159
float K_KP_5
Definition: keycodes.qc:58
float ymax
Definition: mapvoting.qh:20
float mv_votes[MAPVOTE_COUNT]
Definition: mapvoting.qc:24
#define make_pure(e)
Definition: oo.qh:12
float mv_detail
Definition: mapvoting.qc:30
void GameTypeVote_ReadOption(int i)
Definition: mapvoting.qc:619
void Cmd_MapVote_MapDownload(int argc)
Definition: mapvoting.qc:506
NET_HANDLE(ENT_CLIENT_MAPVOTE, bool isnew)
Definition: mapvoting.qc:942
float MapVote_Selection(vector topleft, vector cellsize, float rows, float columns)
Definition: mapvoting.qc:310
bool PreviewExists(string name)
Definition: mapvoting.qc:49
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define tokenize_console
Definition: dpextensions.qh:24
float gametypevote
Definition: mapvoting.qc:40
float mv_timeout
Definition: mapvoting.qc:31
next
Definition: all.qh:88
string MapInfo_Type_Description(Gametype t)
Definition: mapinfo.qc:611
float K_MOUSE1
Definition: keycodes.qc:129
float K_KP_6
Definition: keycodes.qc:59
int mv_columns
Definition: mapvoting.qc:36
void drawborderlines(float thickness, vector pos, vector dim, vector color, float theAlpha, float drawflag)
Definition: draw.qc:5
vector mousepos
Definition: hud.qh:102
#define tokenizebyseparator
Definition: dpextensions.qh:21
void MapVote_Init()
Definition: mapvoting.qc:663
#define vec2(...)
Definition: vector.qh:90
float K_LEFTARROW
Definition: keycodes.qc:17
vector hud_fontsize
Definition: main.qh:63
string mv_pk3[MAPVOTE_COUNT]
Definition: mapvoting.qc:21
void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float _count, int id)
Definition: mapvoting.qc:96
float K_ENTER
Definition: keycodes.qc:8
float ymin
Definition: mapvoting.qh:20
void
Definition: self.qh:83
const int S_CTRL
Definition: hud.qh:128
string getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
Definition: util.qc:880
float time
Definition: csprogsdefs.qc:16
#define HUD_Write_Cvar(cvar)
Definition: hud_config.qh:38
ERASEABLE bool fexists(string f)
Definition: file.qh:4
void MapVote_UpdateVotes()
Definition: mapvoting.qc:923
float mv_top2_alpha
Definition: mapvoting.qc:33
string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, vector fontsize)
Definition: mapvoting.qc:62
bool autocvar_hud_cursormode
Definition: hud.qh:188
void MapVote_Draw_Export(int fh)
Definition: mapvoting.qc:11
void MapVote_SendChoice(int index)
Definition: mapvoting.qc:722
float K_KP_0
Definition: keycodes.qc:48
void MapVote_ReadMask()
Definition: mapvoting.qc:574
void HUD_Panel_LoadCvars()
Definition: hud.qc:216
int mv_mouse_selection
Definition: mapvoting.qc:37
float panel_bg_padding
Definition: hud.qh:171
void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, string pic, float _count, int id)
Definition: mapvoting.qc:208
float xmax
Definition: mapvoting.qh:20