]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qc
Merge branch 'master' into terencehill/lms_updates
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / gamemodes / gamemode / ctf / cl_ctf.qc
1 #include "cl_ctf.qh"
2
3 #include <common/mutators/base.qh>
4 #include <client/draw.qh>
5 #include <client/hud/_mod.qh>
6 #include <client/hud/panel/modicons.qh>
7
8 // CTF HUD modicon section
9 int redflag_prevframe, blueflag_prevframe, yellowflag_prevframe, pinkflag_prevframe, neutralflag_prevframe; // status during previous frame
10 int redflag_prevstatus, blueflag_prevstatus, yellowflag_prevstatus, pinkflag_prevstatus, neutralflag_prevstatus; // last remembered status
11 float redflag_statuschange_time, blueflag_statuschange_time, yellowflag_statuschange_time, pinkflag_statuschange_time, neutralflag_statuschange_time; // time when the status changed
12
13 void HUD_Mod_CTF_Reset()
14 {
15     redflag_prevstatus = blueflag_prevstatus = yellowflag_prevstatus = pinkflag_prevstatus = neutralflag_prevstatus = 0;
16     redflag_prevframe = blueflag_prevframe = yellowflag_prevframe = pinkflag_prevframe = neutralflag_prevframe = 0;
17     redflag_statuschange_time = blueflag_statuschange_time = yellowflag_statuschange_time = pinkflag_statuschange_time = neutralflag_statuschange_time = 0;
18 }
19
20 int autocvar__teams_available;
21 void HUD_Mod_CTF(vector pos, vector mySize)
22 {
23     vector redflag_pos, blueflag_pos, yellowflag_pos, pinkflag_pos, neutralflag_pos;
24     vector flag_size;
25     float f; // every function should have that
26
27     int redflag, blueflag, yellowflag, pinkflag, neutralflag; // current status
28     float redflag_statuschange_elapsedtime = 0, blueflag_statuschange_elapsedtime = 0, yellowflag_statuschange_elapsedtime = 0, pinkflag_statuschange_elapsedtime = 0, neutralflag_statuschange_elapsedtime = 0; // time since the status changed
29     bool ctf_oneflag; // one-flag CTF mode enabled/disabled
30     bool ctf_stalemate; // currently in stalemate
31     int stat_items = STAT(OBJECTIVE_STATUS);
32     float fs, fs2, fs3, size1, size2;
33     vector e1, e2;
34
35     int nteams = autocvar__teams_available;
36
37     redflag = (stat_items/CTF_RED_FLAG_TAKEN) & 3;
38     blueflag = (stat_items/CTF_BLUE_FLAG_TAKEN) & 3;
39     yellowflag = (stat_items/CTF_YELLOW_FLAG_TAKEN) & 3;
40     pinkflag = (stat_items/CTF_PINK_FLAG_TAKEN) & 3;
41     neutralflag = (stat_items/CTF_NEUTRAL_FLAG_TAKEN) & 3;
42
43     ctf_oneflag = (stat_items & CTF_FLAG_NEUTRAL);
44
45     ctf_stalemate = (stat_items & CTF_STALEMATE);
46
47     mod_active = (redflag || blueflag || yellowflag || pinkflag || neutralflag || (stat_items & CTF_SHIELDED));
48
49     if (autocvar__hud_configure) {
50         redflag = 1;
51         blueflag = 2;
52         if (nteams & BIT(2))
53             yellowflag = 2;
54         if (nteams & BIT(3))
55             pinkflag = 3;
56         ctf_oneflag = neutralflag = 0; // disable neutral flag in hud editor?
57     }
58
59     // when status CHANGES, set old status into prevstatus and current status into status
60     #define X(team) MACRO_BEGIN \
61         if (team##flag != team##flag_prevframe) { \
62             team##flag_statuschange_time = time; \
63             team##flag_prevstatus = team##flag_prevframe; \
64             team##flag_prevframe = team##flag; \
65         } \
66         team##flag_statuschange_elapsedtime = time - team##flag_statuschange_time; \
67     MACRO_END
68     X(red);
69     X(blue);
70     X(yellow);
71     X(pink);
72     X(neutral);
73     #undef X
74
75     #define X(team, cond) \
76     string team##_icon = string_null, team##_icon_prevstatus = string_null; \
77     int team##_alpha, team##_alpha_prevstatus; \
78     team##_alpha = team##_alpha_prevstatus = 1; \
79     MACRO_BEGIN \
80         switch (team##flag) { \
81             case 1: team##_icon = "flag_" #team "_taken"; break; \
82             case 2: team##_icon = "flag_" #team "_lost"; break; \
83             case 3: team##_icon = "flag_" #team "_carrying"; team##_alpha = blink(0.85, 0.15, 5); break; \
84             default: \
85                 if ((stat_items & CTF_SHIELDED) && (cond)) { \
86                     team##_icon = "flag_" #team "_shielded"; \
87                 } else { \
88                     team##_icon = string_null; \
89                 } \
90                 break; \
91         } \
92         switch (team##flag_prevstatus) { \
93             case 1: team##_icon_prevstatus = "flag_" #team "_taken"; break; \
94             case 2: team##_icon_prevstatus = "flag_" #team "_lost"; break; \
95             case 3: team##_icon_prevstatus = "flag_" #team "_carrying"; team##_alpha_prevstatus = blink(0.85, 0.15, 5); break; \
96             default: \
97                 if (team##flag == 3) { \
98                     team##_icon_prevstatus = "flag_" #team "_carrying"; /* make it more visible */\
99                 } else if((stat_items & CTF_SHIELDED) && (cond)) { \
100                     team##_icon_prevstatus = "flag_" #team "_shielded"; \
101                 } else { \
102                     team##_icon_prevstatus = string_null; \
103                 } \
104                 break; \
105         } \
106     MACRO_END
107     X(red, myteam != NUM_TEAM_1 && (nteams & BIT(0)));
108     X(blue, myteam != NUM_TEAM_2 && (nteams & BIT(1)));
109     X(yellow, myteam != NUM_TEAM_3 && (nteams & BIT(2)));
110     X(pink, myteam != NUM_TEAM_4 && (nteams & BIT(3)));
111     X(neutral, ctf_oneflag);
112     #undef X
113
114     int tcount = 2;
115     if(nteams & BIT(2))
116         tcount = 3;
117     if(nteams & BIT(3))
118         tcount = 4;
119
120     if (ctf_oneflag) {
121         // hacky, but these aren't needed
122         red_icon = red_icon_prevstatus = blue_icon = blue_icon_prevstatus = yellow_icon = yellow_icon_prevstatus = pink_icon = pink_icon_prevstatus = string_null;
123         fs = fs2 = fs3 = 1;
124     } else switch (tcount) {
125         default:
126         case 2: fs = 0.5; fs2 = 0.5; fs3 = 0.5; break;
127         case 3: fs = 1; fs2 = 0.35; fs3 = 0.35; break;
128         case 4: fs = 0.75; fs2 = 0.25; fs3 = 0.5; break;
129     }
130
131     if (mySize_x > mySize_y) {
132         size1 = mySize_x;
133         size2 = mySize_y;
134         e1 = eX;
135         e2 = eY;
136     } else {
137         size1 = mySize_y;
138         size2 = mySize_x;
139         e1 = eY;
140         e2 = eX;
141     }
142
143     switch (myteam) {
144         default:
145         case NUM_TEAM_1: {
146             redflag_pos = pos;
147             blueflag_pos = pos + eX * fs2 * size1;
148             yellowflag_pos = pos - eX * fs2 * size1;
149             pinkflag_pos = pos + eX * fs3 * size1;
150             break;
151         }
152         case NUM_TEAM_2: {
153             redflag_pos = pos + eX * fs2 * size1;
154             blueflag_pos = pos;
155             yellowflag_pos = pos - eX * fs2 * size1;
156             pinkflag_pos = pos + eX * fs3 * size1;
157             break;
158         }
159         case NUM_TEAM_3: {
160             redflag_pos = pos + eX * fs3 * size1;
161             blueflag_pos = pos - eX * fs2 * size1;
162             yellowflag_pos = pos;
163             pinkflag_pos = pos + eX * fs2 * size1;
164             break;
165         }
166         case NUM_TEAM_4: {
167             redflag_pos = pos - eX * fs2 * size1;
168             blueflag_pos = pos + eX * fs3 * size1;
169             yellowflag_pos = pos + eX * fs2 * size1;
170             pinkflag_pos = pos;
171             break;
172         }
173     }
174     neutralflag_pos = pos;
175     flag_size = e1 * fs * size1 + e2 * size2;
176
177     #define X(team) MACRO_BEGIN \
178         f = bound(0, team##flag_statuschange_elapsedtime * 2, 1); \
179         if (team##_icon && ctf_stalemate) \
180             drawpic_aspect_skin(team##flag_pos, "flag_stalemate", flag_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); \
181         if (team##_icon_prevstatus && f < 1) \
182             drawpic_aspect_skin_expanding(team##flag_pos, team##_icon_prevstatus, flag_size, '1 1 1', panel_fg_alpha * team##_alpha_prevstatus, DRAWFLAG_NORMAL, f); \
183         if (team##_icon) \
184             drawpic_aspect_skin(team##flag_pos, team##_icon, flag_size, '1 1 1', panel_fg_alpha * team##_alpha * f, DRAWFLAG_NORMAL); \
185     MACRO_END
186     X(red);
187     X(blue);
188     X(yellow);
189     X(pink);
190     X(neutral);
191     #undef X
192 }
193
194 bool autocvar_hud_panel_scoreboard_ctf_leaderboard = true;
195
196 REGISTER_MUTATOR(cl_ctf, true);
197
198 MUTATOR_HOOKFUNCTION(cl_ctf, ShowRankings)
199 {
200     if(autocvar_hud_panel_scoreboard_ctf_leaderboard && ISGAMETYPE(CTF) && STAT(CTF_SHOWLEADERBOARD))
201     {
202         M_ARGV(0, string) = _("Capture time rankings");
203         return true;
204     }
205 }