1 /*
2 ** playermenu.cpp
3 ** The player setup menu
4 **
5 **---------------------------------------------------------------------------
6 ** Copyright 2001-2010 Randy Heit
7 ** Copyright 2010 Christoph Oelckers
8 ** All rights reserved.
9 **
10 ** Redistribution and use in source and binary forms, with or without
11 ** modification, are permitted provided that the following conditions
12 ** are met:
13 **
14 ** 1. Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** 2. Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in the
18 ** documentation and/or other materials provided with the distribution.
19 ** 3. The name of the author may not be used to endorse or promote products
20 ** derived from this software without specific prior written permission.
21 **
22 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 **---------------------------------------------------------------------------
33 **
34 */
35
36 #include "menu/menu.h"
37 #include "v_video.h"
38 #include "v_font.h"
39 #include "gi.h"
40 #include "gstrings.h"
41 #include "d_player.h"
42 #include "d_event.h"
43 #include "d_gui.h"
44 #include "c_dispatch.h"
45 #include "teaminfo.h"
46 #include "v_palette.h"
47 #include "r_state.h"
48 #include "r_data/r_translate.h"
49 #include "v_text.h"
50
EXTERN_CVAR(String,playerclass)51 EXTERN_CVAR (String, playerclass)
52 EXTERN_CVAR (String, name)
53 EXTERN_CVAR (Int, team)
54 EXTERN_CVAR (Float, autoaim)
55 EXTERN_CVAR(Bool, neverswitchonpickup)
56 EXTERN_CVAR (Bool, cl_run)
57
58 //=============================================================================
59 //
60 // Player's name
61 //
62 //=============================================================================
63
64 FPlayerNameBox::FPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action)
65 : FListMenuItemSelectable(x, y, height, action)
66 {
67 mText = copystring(text);
68 mFont = font;
69 mFontColor = color;
70 mFrameSize = frameofs;
71 mPlayerName[0] = 0;
72 mEntering = false;
73 }
74
~FPlayerNameBox()75 FPlayerNameBox::~FPlayerNameBox()
76 {
77 if (mText != NULL) delete [] mText;
78 }
79
80 //=============================================================================
81 //
82 //
83 //
84 //=============================================================================
85
SetString(int i,const char * s)86 bool FPlayerNameBox::SetString(int i, const char *s)
87 {
88 if (i == 0)
89 {
90 strncpy(mPlayerName, s, MAXPLAYERNAME);
91 mPlayerName[MAXPLAYERNAME] = 0;
92 return true;
93 }
94 return false;
95 }
96
GetString(int i,char * s,int len)97 bool FPlayerNameBox::GetString(int i, char *s, int len)
98 {
99 if (i == 0)
100 {
101 strncpy(s, mPlayerName, len);
102 s[len] = 0;
103 return true;
104 }
105 return false;
106 }
107
108 //=============================================================================
109 //
110 // [RH] Width of the border is variable
111 //
112 //=============================================================================
113
DrawBorder(int x,int y,int len)114 void FPlayerNameBox::DrawBorder (int x, int y, int len)
115 {
116 FTexture *left = TexMan[TexMan.CheckForTexture("M_LSLEFT", FTexture::TEX_MiscPatch)];
117 FTexture *mid = TexMan[TexMan.CheckForTexture("M_LSCNTR", FTexture::TEX_MiscPatch)];
118 FTexture *right = TexMan[TexMan.CheckForTexture("M_LSRGHT", FTexture::TEX_MiscPatch)];
119 if (left != NULL && right != NULL && mid != NULL)
120 {
121 int i;
122
123 screen->DrawTexture (left, x-8, y+7, DTA_Clean, true, TAG_DONE);
124
125 for (i = 0; i < len; i++)
126 {
127 screen->DrawTexture (mid, x, y+7, DTA_Clean, true, TAG_DONE);
128 x += 8;
129 }
130
131 screen->DrawTexture (right, x, y+7, DTA_Clean, true, TAG_DONE);
132 }
133 else
134 {
135 FTexture *slot = TexMan[TexMan.CheckForTexture("M_FSLOT", FTexture::TEX_MiscPatch)];
136 if (slot != NULL)
137 {
138 screen->DrawTexture (slot, x, y+1, DTA_Clean, true, TAG_DONE);
139 }
140 else
141 {
142 screen->Clear(x, y, x + len, y + SmallFont->GetHeight() * 3/2, -1, 0);
143 }
144 }
145 }
146
147 //=============================================================================
148 //
149 //
150 //
151 //=============================================================================
152
Drawer(bool selected)153 void FPlayerNameBox::Drawer(bool selected)
154 {
155 const char *text = mText;
156 if (text != NULL)
157 {
158 if (*text == '$') text = GStrings(text+1);
159 screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
160 }
161
162 // Draw player name box
163 int x = mXpos + mFont->StringWidth(text) + 16 + mFrameSize;
164 DrawBorder (x, mYpos - mFrameSize, MAXPLAYERNAME+1);
165 if (!mEntering)
166 {
167 screen->DrawText (SmallFont, CR_UNTRANSLATED, x + mFrameSize, mYpos, mPlayerName,
168 DTA_Clean, true, TAG_DONE);
169 }
170 else
171 {
172 size_t l = strlen(mEditName);
173 mEditName[l] = SmallFont->GetCursor();
174 mEditName[l+1] = 0;
175
176 screen->DrawText (SmallFont, CR_UNTRANSLATED, x + mFrameSize, mYpos, mEditName,
177 DTA_Clean, true, TAG_DONE);
178
179 mEditName[l] = 0;
180 }
181 }
182
183 //=============================================================================
184 //
185 //
186 //
187 //=============================================================================
188
MenuEvent(int mkey,bool fromcontroller)189 bool FPlayerNameBox::MenuEvent(int mkey, bool fromcontroller)
190 {
191 if (mkey == MKEY_Enter)
192 {
193 S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", snd_menuvolume, ATTN_NONE);
194 strcpy(mEditName, mPlayerName);
195 mEntering = true;
196 DMenu *input = new DTextEnterMenu(DMenu::CurrentMenu, mEditName, MAXPLAYERNAME, 2, fromcontroller);
197 M_ActivateMenu(input);
198 return true;
199 }
200 else if (mkey == MKEY_Input)
201 {
202 strcpy(mPlayerName, mEditName);
203 mEntering = false;
204 return true;
205 }
206 else if (mkey == MKEY_Abort)
207 {
208 mEntering = false;
209 return true;
210 }
211 return false;
212 }
213
214 //=============================================================================
215 //
216 // items for the player menu
217 //
218 //=============================================================================
219
FValueTextItem(int x,int y,int height,const char * text,FFont * font,EColorRange color,EColorRange valuecolor,FName action,FName values)220 FValueTextItem::FValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values)
221 : FListMenuItemSelectable(x, y, height, action)
222 {
223 mText = copystring(text);
224 mFont = font;
225 mFontColor = color;
226 mFontColor2 = valuecolor;
227 mSelection = 0;
228 if (values != NAME_None)
229 {
230 FOptionValues **opt = OptionValues.CheckKey(values);
231 if (opt != NULL)
232 {
233 for(unsigned i=0;i<(*opt)->mValues.Size(); i++)
234 {
235 SetString(i, (*opt)->mValues[i].Text);
236 }
237 }
238 }
239 }
240
~FValueTextItem()241 FValueTextItem::~FValueTextItem()
242 {
243 if (mText != NULL) delete [] mText;
244 }
245
246 //=============================================================================
247 //
248 //
249 //
250 //=============================================================================
251
SetString(int i,const char * s)252 bool FValueTextItem::SetString(int i, const char *s)
253 {
254 // should actually use the index...
255 FString str = s;
256 if (i==0) mSelections.Clear();
257 mSelections.Push(str);
258 return true;
259 }
260
261 //=============================================================================
262 //
263 //
264 //
265 //=============================================================================
266
SetValue(int i,int value)267 bool FValueTextItem::SetValue(int i, int value)
268 {
269 if (i == 0)
270 {
271 mSelection = value;
272 return true;
273 }
274 return false;
275 }
276
GetValue(int i,int * pvalue)277 bool FValueTextItem::GetValue(int i, int *pvalue)
278 {
279 if (i == 0)
280 {
281 *pvalue = mSelection;
282 return true;
283 }
284 return false;
285 }
286
287 //=============================================================================
288 //
289 //
290 //
291 //=============================================================================
292
MenuEvent(int mkey,bool fromcontroller)293 bool FValueTextItem::MenuEvent (int mkey, bool fromcontroller)
294 {
295 if (mSelections.Size() > 1)
296 {
297 if (mkey == MKEY_Left)
298 {
299 S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
300 if (--mSelection < 0) mSelection = mSelections.Size() - 1;
301 return true;
302 }
303 else if (mkey == MKEY_Right || mkey == MKEY_Enter)
304 {
305 S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
306 if (++mSelection >= (int)mSelections.Size()) mSelection = 0;
307 return true;
308 }
309 }
310 return (mkey == MKEY_Enter); // needs to eat enter keys so that Activate won't get called
311 }
312
313 //=============================================================================
314 //
315 //
316 //
317 //=============================================================================
318
Drawer(bool selected)319 void FValueTextItem::Drawer(bool selected)
320 {
321 const char *text = mText;
322
323 if (*text == '$') text = GStrings(text+1);
324 screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
325
326 int x = mXpos + mFont->StringWidth(text) + 8;
327 if (mSelections.Size() > 0)
328 {
329 const char *mOptValue = mSelections[mSelection];
330 if (*mOptValue == '$') mOptValue = GStrings(mOptValue + 1);
331 screen->DrawText(mFont, mFontColor2, x, mYpos, mOptValue, DTA_Clean, true, TAG_DONE);
332 }
333 }
334
335 //=============================================================================
336 //
337 // items for the player menu
338 //
339 //=============================================================================
340
FSliderItem(int x,int y,int height,const char * text,FFont * font,EColorRange color,FName action,int min,int max,int step)341 FSliderItem::FSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step)
342 : FListMenuItemSelectable(x, y, height, action)
343 {
344 mText = copystring(text);
345 mFont = font;
346 mFontColor = color;
347 mSelection = 0;
348 mMinrange = min;
349 mMaxrange = max;
350 mStep = step;
351 }
352
~FSliderItem()353 FSliderItem::~FSliderItem()
354 {
355 if (mText != NULL) delete [] mText;
356 }
357
358 //=============================================================================
359 //
360 //
361 //
362 //=============================================================================
363
SetValue(int i,int value)364 bool FSliderItem::SetValue(int i, int value)
365 {
366 if (i == 0)
367 {
368 mSelection = value;
369 return true;
370 }
371 return false;
372 }
373
GetValue(int i,int * pvalue)374 bool FSliderItem::GetValue(int i, int *pvalue)
375 {
376 if (i == 0)
377 {
378 *pvalue = mSelection;
379 return true;
380 }
381 return false;
382 }
383
384 //=============================================================================
385 //
386 //
387 //
388 //=============================================================================
389
MenuEvent(int mkey,bool fromcontroller)390 bool FSliderItem::MenuEvent (int mkey, bool fromcontroller)
391 {
392 if (mkey == MKEY_Left)
393 {
394 S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
395 if ((mSelection -= mStep) < mMinrange) mSelection = mMinrange;
396 return true;
397 }
398 else if (mkey == MKEY_Right || mkey == MKEY_Enter)
399 {
400 S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
401 if ((mSelection += mStep) > mMaxrange) mSelection = mMaxrange;
402 return true;
403 }
404 return false;
405 }
406
407 //=============================================================================
408 //
409 //
410 //
411 //=============================================================================
412
MouseEvent(int type,int x,int y)413 bool FSliderItem::MouseEvent(int type, int x, int y)
414 {
415 DListMenu *lm = static_cast<DListMenu*>(DMenu::CurrentMenu);
416 if (type != DMenu::MOUSE_Click)
417 {
418 if (!lm->CheckFocus(this)) return false;
419 }
420 if (type == DMenu::MOUSE_Release)
421 {
422 lm->ReleaseFocus();
423 }
424
425 int slide_left = SmallFont->StringWidth ("Green") + 8 + mXpos;
426 int slide_right = slide_left + 12*8; // 12 char cells with 8 pixels each.
427
428 if (type == DMenu::MOUSE_Click)
429 {
430 if (x < slide_left || x >= slide_right) return true;
431 }
432
433 x = clamp(x, slide_left, slide_right);
434 int v = mMinrange + Scale(x - slide_left, mMaxrange - mMinrange, slide_right - slide_left);
435 if (v != mSelection)
436 {
437 mSelection = v;
438 S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", snd_menuvolume, ATTN_NONE);
439 }
440 if (type == DMenu::MOUSE_Click)
441 {
442 lm->SetFocus(this);
443 }
444 return true;
445 }
446
447 //=============================================================================
448 //
449 //
450 //
451 //=============================================================================
452
DrawSlider(int x,int y)453 void FSliderItem::DrawSlider (int x, int y)
454 {
455 int range = mMaxrange - mMinrange;
456 int cur = mSelection - mMinrange;
457
458 x = (x - 160) * CleanXfac + screen->GetWidth() / 2;
459 y = (y - 100) * CleanYfac + screen->GetHeight() / 2;
460
461 screen->DrawText (ConFont, CR_WHITE, x, y,
462 "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12",
463 DTA_CellX, 8 * CleanXfac,
464 DTA_CellY, 8 * CleanYfac,
465 TAG_DONE);
466 screen->DrawText (ConFont, CR_ORANGE, x + (5 + (int)((cur * 78) / range)) * CleanXfac, y,
467 "\x13",
468 DTA_CellX, 8 * CleanXfac,
469 DTA_CellY, 8 * CleanYfac,
470 TAG_DONE);
471 }
472
473 //=============================================================================
474 //
475 //
476 //
477 //=============================================================================
478
Drawer(bool selected)479 void FSliderItem::Drawer(bool selected)
480 {
481 const char *text = mText;
482
483 if (*text == '$') text = GStrings(text+1);
484 screen->DrawText(mFont, selected? OptionSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true, TAG_DONE);
485
486 int x = SmallFont->StringWidth ("Green") + 8 + mXpos;
487 int x2 = SmallFont->StringWidth (text) + 8 + mXpos;
488 DrawSlider (MAX(x2, x), mYpos);
489 }
490
491
492 //=============================================================================
493 //
494 //
495 //
496 //=============================================================================
497
498 class DPlayerMenu : public DListMenu
499 {
500 DECLARE_CLASS(DPlayerMenu, DListMenu)
501
502 int PlayerClassIndex;
503 FPlayerClass *PlayerClass;
504 TArray<int> PlayerColorSets;
505 TArray<int> PlayerSkins;
506 int mRotation;
507
508 void PickPlayerClass ();
509 void UpdateColorsets();
510 void UpdateSkins();
511 void UpdateTranslation();
512 void SendNewColor (int red, int green, int blue);
513
514 void PlayerNameChanged(FListMenuItem *li);
515 void ColorSetChanged (FListMenuItem *li);
516 void ClassChanged (FListMenuItem *li);
517 void AutoaimChanged (FListMenuItem *li);
518 void SkinChanged (FListMenuItem *li);
519
520
521 public:
522
DPlayerMenu()523 DPlayerMenu() {}
524 void Init(DMenu *parent, FListMenuDescriptor *desc);
525 bool Responder (event_t *ev);
526 bool MenuEvent (int mkey, bool fromcontroller);
527 bool MouseEvent(int type, int x, int y);
528 void Ticker ();
529 void Drawer ();
530 };
531
IMPLEMENT_CLASS(DPlayerMenu)532 IMPLEMENT_CLASS(DPlayerMenu)
533
534 //=============================================================================
535 //
536 //
537 //
538 //=============================================================================
539
540 void DPlayerMenu::Init(DMenu *parent, FListMenuDescriptor *desc)
541 {
542 FListMenuItem *li;
543
544 Super::Init(parent, desc);
545 PickPlayerClass();
546 mRotation = 0;
547
548 li = GetItem(NAME_Playerdisplay);
549 if (li != NULL)
550 {
551 li->SetValue(FListMenuItemPlayerDisplay::PDF_ROTATION, 0);
552 li->SetValue(FListMenuItemPlayerDisplay::PDF_MODE, 1);
553 li->SetValue(FListMenuItemPlayerDisplay::PDF_TRANSLATE, 1);
554 li->SetValue(FListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
555 if (PlayerClass != NULL && !(GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN) &&
556 players[consoleplayer].userinfo.GetPlayerClassNum() != -1)
557 {
558 li->SetValue(FListMenuItemPlayerDisplay::PDF_SKIN, players[consoleplayer].userinfo.GetSkin());
559 }
560 }
561
562 li = GetItem(NAME_Playerbox);
563 if (li != NULL)
564 {
565 li->SetString(0, name);
566 }
567
568 li = GetItem(NAME_Team);
569 if (li != NULL)
570 {
571 li->SetString(0, "None");
572 for(unsigned i=0;i<Teams.Size(); i++)
573 {
574 li->SetString(i+1, Teams[i].GetName());
575 }
576 li->SetValue(0, team == TEAM_NONE? 0 : team + 1);
577 }
578
579 int mycolorset = players[consoleplayer].userinfo.GetColorSet();
580 int color = players[consoleplayer].userinfo.GetColor();
581
582 UpdateColorsets();
583
584 li = GetItem(NAME_Red);
585 if (li != NULL)
586 {
587 li->Enable(mycolorset == -1);
588 li->SetValue(0, RPART(color));
589 }
590
591 li = GetItem(NAME_Green);
592 if (li != NULL)
593 {
594 li->Enable(mycolorset == -1);
595 li->SetValue(0, GPART(color));
596 }
597
598 li = GetItem(NAME_Blue);
599 if (li != NULL)
600 {
601 li->Enable(mycolorset == -1);
602 li->SetValue(0, BPART(color));
603 }
604
605 li = GetItem(NAME_Class);
606 if (li != NULL)
607 {
608 if (PlayerClasses.Size() == 1)
609 {
610 li->SetString(0, GetPrintableDisplayName(PlayerClasses[0].Type));
611 li->SetValue(0, 0);
612 }
613 else
614 {
615 // [XA] Remove the "Random" option if the relevant gameinfo flag is set.
616 if(!gameinfo.norandomplayerclass)
617 li->SetString(0, "Random");
618 for(unsigned i=0; i< PlayerClasses.Size(); i++)
619 {
620 const char *cls = GetPrintableDisplayName(PlayerClasses[i].Type);
621 li->SetString(gameinfo.norandomplayerclass ? i : i+1, cls);
622 }
623 int pclass = players[consoleplayer].userinfo.GetPlayerClassNum();
624 li->SetValue(0, gameinfo.norandomplayerclass && pclass >= 0 ? pclass : pclass + 1);
625 }
626 }
627
628 UpdateSkins();
629
630 li = GetItem(NAME_Gender);
631 if (li != NULL)
632 {
633 li->SetValue(0, players[consoleplayer].userinfo.GetGender());
634 }
635
636 li = GetItem(NAME_Autoaim);
637 if (li != NULL)
638 {
639 li->SetValue(0, (int)autoaim);
640 }
641
642 li = GetItem(NAME_Switch);
643 if (li != NULL)
644 {
645 li->SetValue(0, neverswitchonpickup);
646 }
647
648 li = GetItem(NAME_AlwaysRun);
649 if (li != NULL)
650 {
651 li->SetValue(0, cl_run);
652 }
653
654 if (mDesc->mSelectedItem < 0) mDesc->mSelectedItem = 1;
655
656 }
657
658 //=============================================================================
659 //
660 //
661 //
662 //=============================================================================
663
Responder(event_t * ev)664 bool DPlayerMenu::Responder (event_t *ev)
665 {
666 if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_Char && ev->data1 == ' ')
667 {
668 // turn the player sprite around
669 mRotation = 8 - mRotation;
670 FListMenuItem *li = GetItem(NAME_Playerdisplay);
671 if (li != NULL)
672 {
673 li->SetValue(FListMenuItemPlayerDisplay::PDF_ROTATION, mRotation);
674 }
675 return true;
676 }
677 return Super::Responder(ev);
678 }
679
680 //=============================================================================
681 //
682 //
683 //
684 //=============================================================================
685
UpdateTranslation()686 void DPlayerMenu::UpdateTranslation()
687 {
688 int PlayerColor = players[consoleplayer].userinfo.GetColor();
689 int PlayerSkin = players[consoleplayer].userinfo.GetSkin();
690 int PlayerColorset = players[consoleplayer].userinfo.GetColorSet();
691
692 if (PlayerClass != NULL)
693 {
694 PlayerSkin = R_FindSkin (skins[PlayerSkin].name, int(PlayerClass - &PlayerClasses[0]));
695 R_GetPlayerTranslation(PlayerColor,
696 P_GetPlayerColorSet(PlayerClass->Type->TypeName, PlayerColorset),
697 &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
698 }
699 }
700
701 //=============================================================================
702 //
703 //
704 //
705 //=============================================================================
706
PickPlayerClass()707 void DPlayerMenu::PickPlayerClass()
708 {
709
710 /*
711 // What's the point of this? Aren't we supposed to edit the
712 // userinfo?
713 if (players[consoleplayer].mo != NULL)
714 {
715 PlayerClassIndex = players[consoleplayer].CurrentPlayerClass;
716 }
717 else
718 */
719 {
720 int pclass = 0;
721 // [GRB] Pick a class from player class list
722 if (PlayerClasses.Size () > 1)
723 {
724 pclass = players[consoleplayer].userinfo.GetPlayerClassNum();
725
726 if (pclass < 0)
727 {
728 pclass = (MenuTime>>7) % PlayerClasses.Size ();
729 }
730 }
731 PlayerClassIndex = pclass;
732 }
733 PlayerClass = &PlayerClasses[PlayerClassIndex];
734 UpdateTranslation();
735 }
736
737 //=============================================================================
738 //
739 //
740 //
741 //=============================================================================
742
SendNewColor(int red,int green,int blue)743 void DPlayerMenu::SendNewColor (int red, int green, int blue)
744 {
745 char command[24];
746
747 players[consoleplayer].userinfo.ColorChanged(MAKERGB(red,green,blue));
748 mysnprintf (command, countof(command), "color \"%02x %02x %02x\"", red, green, blue);
749 C_DoCommand (command);
750 UpdateTranslation();
751 }
752
753 //=============================================================================
754 //
755 //
756 //
757 //=============================================================================
758
UpdateColorsets()759 void DPlayerMenu::UpdateColorsets()
760 {
761 FListMenuItem *li = GetItem(NAME_Color);
762 if (li != NULL)
763 {
764 int sel = 0;
765 P_EnumPlayerColorSets(PlayerClass->Type->TypeName, &PlayerColorSets);
766 li->SetString(0, "Custom");
767 for(unsigned i=0;i<PlayerColorSets.Size(); i++)
768 {
769 FPlayerColorSet *colorset = P_GetPlayerColorSet(PlayerClass->Type->TypeName, PlayerColorSets[i]);
770 li->SetString(i+1, colorset->Name);
771 }
772 int mycolorset = players[consoleplayer].userinfo.GetColorSet();
773 if (mycolorset != -1)
774 {
775 for(unsigned i=0;i<PlayerColorSets.Size(); i++)
776 {
777 if (PlayerColorSets[i] == mycolorset)
778 {
779 sel = i+1;
780 }
781 }
782 }
783 li->SetValue(0, sel);
784 }
785 }
786
787 //=============================================================================
788 //
789 //
790 //
791 //=============================================================================
792
UpdateSkins()793 void DPlayerMenu::UpdateSkins()
794 {
795 int sel = 0;
796 int skin;
797 FListMenuItem *li = GetItem(NAME_Skin);
798 if (li != NULL)
799 {
800 if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN ||
801 players[consoleplayer].userinfo.GetPlayerClassNum() == -1)
802 {
803 li->SetString(0, "Base");
804 li->SetValue(0, 0);
805 skin = 0;
806 }
807 else
808 {
809 PlayerSkins.Clear();
810 for(int i=0;i<(int)numskins; i++)
811 {
812 if (PlayerClass->CheckSkin(i))
813 {
814 int j = PlayerSkins.Push(i);
815 li->SetString(j, skins[i].name);
816 if (players[consoleplayer].userinfo.GetSkin() == i)
817 {
818 sel = j;
819 }
820 }
821 }
822 li->SetValue(0, sel);
823 skin = PlayerSkins[sel];
824 }
825 li = GetItem(NAME_Playerdisplay);
826 if (li != NULL)
827 {
828 li->SetValue(FListMenuItemPlayerDisplay::PDF_SKIN, skin);
829 }
830 }
831 UpdateTranslation();
832 }
833
834 //=============================================================================
835 //
836 //
837 //
838 //=============================================================================
839
PlayerNameChanged(FListMenuItem * li)840 void DPlayerMenu::PlayerNameChanged(FListMenuItem *li)
841 {
842 char pp[MAXPLAYERNAME+1];
843 const char *p;
844 if (li->GetString(0, pp, MAXPLAYERNAME))
845 {
846 FString command("name \"");
847
848 // Escape any backslashes or quotation marks before sending the name to the console.
849 for (p = pp; *p != '\0'; ++p)
850 {
851 if (*p == '"' || *p == '\\')
852 {
853 command << '\\';
854 }
855 command << *p;
856 }
857 command << '"';
858 C_DoCommand (command);
859 }
860 }
861
862 //=============================================================================
863 //
864 //
865 //
866 //=============================================================================
867
ColorSetChanged(FListMenuItem * li)868 void DPlayerMenu::ColorSetChanged (FListMenuItem *li)
869 {
870 int sel;
871
872 if (li->GetValue(0, &sel))
873 {
874 int mycolorset = -1;
875
876 if (sel > 0) mycolorset = PlayerColorSets[sel-1];
877
878 FListMenuItem *red = GetItem(NAME_Red);
879 FListMenuItem *green = GetItem(NAME_Green);
880 FListMenuItem *blue = GetItem(NAME_Blue);
881
882 // disable the sliders if a valid colorset is selected
883 if (red != NULL) red->Enable(mycolorset == -1);
884 if (green != NULL) green->Enable(mycolorset == -1);
885 if (blue != NULL) blue->Enable(mycolorset == -1);
886
887 char command[24];
888 players[consoleplayer].userinfo.ColorSetChanged(mycolorset);
889 mysnprintf(command, countof(command), "colorset %d", mycolorset);
890 C_DoCommand(command);
891 UpdateTranslation();
892 }
893 }
894
895 //=============================================================================
896 //
897 //
898 //
899 //=============================================================================
900
ClassChanged(FListMenuItem * li)901 void DPlayerMenu::ClassChanged (FListMenuItem *li)
902 {
903 if (PlayerClasses.Size () == 1)
904 {
905 return;
906 }
907
908 int sel;
909
910 if (li->GetValue(0, &sel))
911 {
912 players[consoleplayer].userinfo.PlayerClassNumChanged(gameinfo.norandomplayerclass ? sel : sel-1);
913 PickPlayerClass();
914
915 cvar_set ("playerclass", sel == 0 && !gameinfo.norandomplayerclass ? "Random" : PlayerClass->Type->Meta.GetMetaString (APMETA_DisplayName));
916
917 UpdateSkins();
918 UpdateColorsets();
919 UpdateTranslation();
920
921 li = GetItem(NAME_Playerdisplay);
922 if (li != NULL)
923 {
924 li->SetValue(FListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum());
925 }
926 }
927 }
928
929 //=============================================================================
930 //
931 //
932 //
933 //=============================================================================
934
SkinChanged(FListMenuItem * li)935 void DPlayerMenu::SkinChanged (FListMenuItem *li)
936 {
937 if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN ||
938 players[consoleplayer].userinfo.GetPlayerClassNum() == -1)
939 {
940 return;
941 }
942
943 int sel;
944
945 if (li->GetValue(0, &sel))
946 {
947 sel = PlayerSkins[sel];
948 players[consoleplayer].userinfo.SkinNumChanged(sel);
949 UpdateTranslation();
950 cvar_set ("skin", skins[sel].name);
951
952 li = GetItem(NAME_Playerdisplay);
953 if (li != NULL)
954 {
955 li->SetValue(FListMenuItemPlayerDisplay::PDF_SKIN, sel);
956 }
957 }
958 }
959
960 //=============================================================================
961 //
962 //
963 //
964 //=============================================================================
965
AutoaimChanged(FListMenuItem * li)966 void DPlayerMenu::AutoaimChanged (FListMenuItem *li)
967 {
968 int sel;
969
970 if (li->GetValue(0, &sel))
971 {
972 autoaim = (float)sel;
973 }
974 }
975
976 //=============================================================================
977 //
978 //
979 //
980 //=============================================================================
981
MenuEvent(int mkey,bool fromcontroller)982 bool DPlayerMenu::MenuEvent (int mkey, bool fromcontroller)
983 {
984 int v;
985 if (mDesc->mSelectedItem >= 0)
986 {
987 FListMenuItem *li = mDesc->mItems[mDesc->mSelectedItem];
988 if (li->MenuEvent(mkey, fromcontroller))
989 {
990 FName current = li->GetAction(NULL);
991 switch(current)
992 {
993 // item specific handling comes here
994
995 case NAME_Playerbox:
996 if (mkey == MKEY_Input)
997 {
998 PlayerNameChanged(li);
999 }
1000 break;
1001
1002 case NAME_Team:
1003 if (li->GetValue(0, &v))
1004 {
1005 team = v==0? TEAM_NONE : v-1;
1006 }
1007 break;
1008
1009 case NAME_Color:
1010 ColorSetChanged(li);
1011 break;
1012
1013 case NAME_Red:
1014 if (li->GetValue(0, &v))
1015 {
1016 uint32 color = players[consoleplayer].userinfo.GetColor();
1017 SendNewColor (v, GPART(color), BPART(color));
1018 }
1019 break;
1020
1021 case NAME_Green:
1022 if (li->GetValue(0, &v))
1023 {
1024 uint32 color = players[consoleplayer].userinfo.GetColor();
1025 SendNewColor (RPART(color), v, BPART(color));
1026 }
1027 break;
1028
1029 case NAME_Blue:
1030 if (li->GetValue(0, &v))
1031 {
1032 uint32 color = players[consoleplayer].userinfo.GetColor();
1033 SendNewColor (RPART(color), GPART(color), v);
1034 }
1035 break;
1036
1037 case NAME_Class:
1038 ClassChanged(li);
1039 break;
1040
1041 case NAME_Skin:
1042 SkinChanged(li);
1043 break;
1044
1045 case NAME_Gender:
1046 if (li->GetValue(0, &v))
1047 {
1048 cvar_set ("gender", v==0? "male" : v==1? "female" : "other");
1049 }
1050 break;
1051
1052 case NAME_Autoaim:
1053 AutoaimChanged(li);
1054 break;
1055
1056 case NAME_Switch:
1057 if (li->GetValue(0, &v))
1058 {
1059 neverswitchonpickup = !!v;
1060 }
1061 break;
1062
1063 case NAME_AlwaysRun:
1064 if (li->GetValue(0, &v))
1065 {
1066 cl_run = !!v;
1067 }
1068 break;
1069
1070 default:
1071 break;
1072 }
1073 return true;
1074 }
1075 }
1076 return Super::MenuEvent(mkey, fromcontroller);
1077 }
1078
1079
MouseEvent(int type,int x,int y)1080 bool DPlayerMenu::MouseEvent(int type, int x, int y)
1081 {
1082 int v;
1083 FListMenuItem *li = mFocusControl;
1084 bool res = Super::MouseEvent(type, x, y);
1085 if (li == NULL) li = mFocusControl;
1086 if (li != NULL)
1087 {
1088 // Check if the colors have changed
1089 FName current = li->GetAction(NULL);
1090 switch(current)
1091 {
1092 case NAME_Red:
1093 if (li->GetValue(0, &v))
1094 {
1095 uint32 color = players[consoleplayer].userinfo.GetColor();
1096 SendNewColor (v, GPART(color), BPART(color));
1097 }
1098 break;
1099
1100 case NAME_Green:
1101 if (li->GetValue(0, &v))
1102 {
1103 uint32 color = players[consoleplayer].userinfo.GetColor();
1104 SendNewColor (RPART(color), v, BPART(color));
1105 }
1106 break;
1107
1108 case NAME_Blue:
1109 if (li->GetValue(0, &v))
1110 {
1111 uint32 color = players[consoleplayer].userinfo.GetColor();
1112 SendNewColor (RPART(color), GPART(color), v);
1113 }
1114 break;
1115 }
1116 }
1117 return res;
1118 }
1119
1120 //=============================================================================
1121 //
1122 //
1123 //
1124 //=============================================================================
1125
Ticker()1126 void DPlayerMenu::Ticker ()
1127 {
1128
1129 Super::Ticker();
1130 }
1131
1132 //=============================================================================
1133 //
1134 //
1135 //
1136 //=============================================================================
1137
Drawer()1138 void DPlayerMenu::Drawer ()
1139 {
1140
1141 Super::Drawer();
1142
1143 const char *str = "PRESS " TEXTCOLOR_WHITE "SPACE";
1144 screen->DrawText (SmallFont, CR_GOLD, 320 - 32 - 32 -
1145 SmallFont->StringWidth (str)/2,
1146 50 + 48 + 70, str,
1147 DTA_Clean, true, TAG_DONE);
1148 str = mRotation ? "TO SEE FRONT" : "TO SEE BACK";
1149 screen->DrawText (SmallFont, CR_GOLD, 320 - 32 - 32 -
1150 SmallFont->StringWidth (str)/2,
1151 50 + 48 + 70 + SmallFont->GetHeight (), str,
1152 DTA_Clean, true, TAG_DONE);
1153
1154 }
1155