Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
campaign.qc
Go to the documentation of this file.
1#include "campaign.qh"
2
4#include "inputbox.qh"
5
7
8void rewrapCampaign(float w, float l0, float emptyheight, vector theFontSize)
9{
10 int i, j;
11 int n;
12 float l;
13 string r, s;
14 for(i = 0; i < campaign_entries; ++i)
15 {
16 l = l0;
18 n = tokenizebyseparator(campaign_longdesc[i], "\n");
19 r = "";
20 for(j = 0; j < n; ++j)
21 {
22 s = argv(j);
23 if(s == "")
24 {
25 l -= emptyheight;
26 r = strcat(r, "\n");
27 continue;
28 }
29
32 {
34 if(--l < 0) goto toolong;
35 r = strcat(r, s, "\n");
36 }
37 }
38 goto nottoolong;
39LABEL(toolong)
40 while(substring(r, strlen(r) - 1, 1) == "\n")
41 r = substring(r, 0, strlen(r) - 1);
42 r = strcat(r, "...\n");
43LABEL(nottoolong)
45 }
46}
47
49{
50 entity me;
52 me.configureXonoticCampaignList(me);
53 return me;
54}
56{
57 me.configureXonoticListBox(me);
58 me.campaignGlob = search_begin("maps/campaign*.txt", true, true);
59 me.loadCvars(me);
60 me.campaignGo(me, 0); // it makes work buttons too
61}
62
64{
65 if(me.campaignGlob >= 0)
66 search_end(me.campaignGlob);
67}
68
70{
71 // read campaign cvars
72 strcpy(campaign_name, cvar_string("g_campaign_name"));
73 strcpy(me.controlledCvar, strcat("g_campaign", campaign_name, "_index"));
74 registercvar(me.controlledCvar, "", 0); // saved by server QC anyway
77 me.campaignIndex = bound(0, cvar(me.controlledCvar), campaign_entries);
78 cvar_set(me.controlledCvar, ftos(me.campaignIndex));
79 if(me.columnNameSize)
80 rewrapCampaign(me.columnNameSize, me.rowsPerItem - 3, me.emptyLineHeight, me.realFontSize);
81 me.nItems = min(me.campaignIndex + 2, campaign_entries);
82 me.setSelected(me, min(me.campaignIndex, me.nItems - 1));
83 if(me.nItems - 1 > me.campaignIndex)
84 me.scrollToItem(me, me.nItems - 1);
85 if(me.labelTitle)
86 me.labelTitle.setText(me.labelTitle, campaign_title);
87}
88
90{
91 // write campaign cvars
92 // no reason to do this!
93 // cvar_set("g_campaign_name", campaign_name);
94 // cvar_set(me.controlledCvar, ftos(me.campaignIndex)); // NOTE: only server QC does that!
95}
96
98{
99 string s;
100 float i, j, n;
101
102 if(me.campaignGlob >= 0)
103 {
104 n = search_getsize(me.campaignGlob);
105 if(n > 0)
106 {
107 j = -1;
108 s = strcat("maps/campaign", campaign_name, ".txt");
109 for(i = 0; i < n; ++i)
110 {
111 if(search_getfilename(me.campaignGlob, i) == s)
112 j = i;
113 }
114 if(j < 0)
115 {
116 s = strcat("maps/campaign", cvar_defstring("g_campaign_name"), ".txt");
117 for(i = 0; i < n; ++i)
118 {
119 if(search_getfilename(me.campaignGlob, i) == s)
120 j = i;
121 }
122 }
123 if(j < 0)
124 {
125 if(step >= 0)
126 j = 0;
127 else
128 j = n - 1;
129 }
130 else
131 j = mod(j + step, n);
132 s = search_getfilename(me.campaignGlob, j);
133 s = substring(s, 13, strlen(s) - 17);
134 cvar_set("g_campaign_name", s);
135 me.loadCvars(me);
136 me.hasNextCampaign = (j != n - 1);
137 me.hasPrevCampaign = (j != 0);
138 }
139 }
140}
141
143{
144 me.campaignGo(me, +1);
145}
147{
148 me.campaignGo(me, -1);
149}
150
152{
153 if(me.buttonNext)
154 me.buttonNext.disabled = !me.hasNextCampaign;
155 if(me.buttonPrev)
156 me.buttonPrev.disabled = !me.hasPrevCampaign;
157
158 if(cvar(me.controlledCvar) != me.campaignIndex || cvar_string("g_campaign_name") != campaign_name)
159 me.loadCvars(me);
160 SUPER(XonoticCampaignList).draw(me);
161}
162
163void XonoticCampaignList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
164{
165 me.itemAbsSize = '0 0 0';
166 SUPER(XonoticCampaignList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
167
168 me.itemAbsSize.y = absSize.y * me.itemHeight;
169 me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
170 me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
171 me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
172 me.realUpperMargin1 = 0.5 * me.realFontSize.y;
173 me.realUpperMargin2 = me.realUpperMargin1 + 2 * me.realFontSize.y;
174
175 me.checkMarkSize = (eX * (me.itemAbsSize.y / me.itemAbsSize.x) + eY) * 0.5;
176
177 me.columnPreviewOrigin = 0;
178 me.columnPreviewSize = me.itemAbsSize.y / me.itemAbsSize.x * 4 / 3;
179 me.columnCheckMarkSize = me.checkMarkSize.x;
180 me.columnNameSize = 1 - me.columnPreviewSize - me.columnCheckMarkSize - 4 * me.realFontSize.x;
181 me.columnNameOrigin = me.columnPreviewOrigin + me.columnPreviewSize + me.realFontSize.x;
182 me.columnCheckMarkOrigin = me.columnNameOrigin + me.columnNameSize + me.realFontSize.x * 2;
183
184 me.checkMarkOrigin = eY + eX * (me.columnCheckMarkOrigin + me.columnCheckMarkSize) - me.checkMarkSize;
185
186 me.typeIconOrigin = vec3(me.columnPreviewSize - me.checkMarkSize.x, me.checkMarkOrigin.y, 0);
187 me.typeIconSize = me.checkMarkSize;
188
189 rewrapCampaign(me.columnNameSize, me.rowsPerItem - 3, me.emptyLineHeight, me.realFontSize);
190}
192{
193 CampaignList_LoadMap(me, me);
194}
195void XonoticCampaignList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
196{
197 string s;
198 vector theColor;
199 float theAlpha;
200 float j, n;
201 vector o;
202
203 if(i < me.campaignIndex)
204 {
205 theAlpha = SKINALPHA_CAMPAIGN_SELECTABLE;
206 theColor = SKINCOLOR_CAMPAIGN_SELECTABLE;
207 }
208 else if(i == me.campaignIndex)
209 {
210 theAlpha = SKINALPHA_CAMPAIGN_CURRENT;
211 theColor = SKINCOLOR_CAMPAIGN_CURRENT;
212 }
213 else
214 {
215 theAlpha = SKINALPHA_CAMPAIGN_FUTURE;
216 theColor = SKINCOLOR_CAMPAIGN_FUTURE;
217 }
218
219 if(isSelected)
220 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
221 else if(isFocused)
222 {
223 me.focusedItemAlpha = getFadedAlpha(me.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED);
224 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, me.focusedItemAlpha);
225 }
226
227 if(draw_PictureSize(strcat("/maps/", campaign_mapname[i])) == '0 0 0')
228 draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
229 else
230 draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", campaign_mapname[i]), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
231
232 s = strcat("gametype_", campaign_gametype[i]);
233 if(i <= me.campaignIndex && draw_PictureSize(s) != '0 0 0')
234 draw_Picture(me.typeIconOrigin, s, me.typeIconSize, '1 1 1', 1);
235
236 if(i < me.campaignIndex)
237 draw_Picture(me.checkMarkOrigin, "checkmark", me.checkMarkSize, '1 1 1', 1);
238
239 if(i <= me.campaignIndex)
240 s = campaign_shortdesc[i]; // fteqcc sucks
241 else
242 s = "???";
243 // NOTE the following string should be equal to the one used in the Welcome dialog
244 // to avoid adding a slightly different string to translate
245 s = draw_TextShortenToWidth(strcat(sprintf(_("Level %d:"), i+1), " ", s), me.columnNameSize, 0, me.realFontSize);
246 draw_Text(me.realUpperMargin1 * eY + (me.columnNameOrigin + 0.00 * (me.columnNameSize - draw_TextWidth(s, 0, me.realFontSize))) * eX, s, me.realFontSize, theColor, theAlpha, 0);
247
248 if(i <= me.campaignIndex)
249 {
251 n = tokenizebyseparator(s, "\n");
252 o = me.realUpperMargin2 * eY + me.columnNameOrigin * eX;
253 for(j = 0; j < n; ++j)
254 if(argv(j) != "")
255 {
256 draw_Text(o, argv(j), me.realFontSize, theColor, theAlpha * SKINALPHA_CAMPAIGN_DESCRIPTION, 0);
257 o.y += me.realFontSize.y;
258 }
259 else
260 o.y += me.realFontSize.y * me.emptyLineHeight;
261 }
262}
264{
265 if(me.selectedItem >= me.nItems || me.selectedItem < 0)
266 return;
267 CampaignSetup(me.selectedItem);
268}
269
271{
272 // prevent too late items from being played
273 SUPER(XonoticCampaignList).setSelected(me, min(i, me.campaignIndex));
274}
275
276float XonoticCampaignList_keyDown(entity me, float scan, float ascii, float shift)
277{
278 if(scan == K_ENTER || scan == K_SPACE || scan == K_KP_ENTER)
279 CampaignList_LoadMap(me, me);
280 else
281 return SUPER(XonoticCampaignList).keyDown(me, scan, ascii, shift);
282 return 1;
283}
string campaign_title
string campaign_name
void CampaignFile_Unload()
string campaign_gametype[CAMPAIGN_MAX_ENTRIES]
#define CAMPAIGN_MAX_ENTRIES
string campaign_mapname[CAMPAIGN_MAX_ENTRIES]
void CampaignSetup(int n)
int campaign_entries
float CampaignFile_Load(float offset, float entries)
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
string getWrappedLine(float maxWidth, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
Definition util.qc:995
string getWrappedLine_remaining
Definition util.qh:147
#define LABEL(id)
Definition compiler.qh:34
#define strlen
#define tokenizebyseparator
float K_SPACE
Definition keycodes.qc:10
float K_ENTER
Definition keycodes.qc:8
float K_KP_ENTER
Definition keycodes.qc:74
string draw_TextShortenToWidth(string theText, float maxWidth, float ICanHasKallerz, vector SizeThxBye)
Definition draw.qc:377
float draw_TextWidth_WithoutColors(string s, vector theFontSize)
Definition draw.qc:396
void draw_Picture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha)
Definition draw.qc:72
void draw_Text(vector theOrigin, string theText, vector theSize, vector theColor, float theAlpha, float ICanHasKallerz)
Definition draw.qc:282
vector draw_PictureSize(string pic)
Definition draw.qc:80
float draw_TextWidth(string theText, float ICanHasKallerz, vector SizeThxBye)
Definition draw.qc:304
void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha)
Definition draw.qc:97
void XonoticCampaignList_campaignGo(entity me, float step)
Definition campaign.qc:97
void XonoticCampaignList_setSelected(entity me, float i)
Definition campaign.qc:270
void MultiCampaign_Prev(entity btn, entity me)
Definition campaign.qc:146
void XonoticCampaignList_doubleClickListBoxItem(entity me, float i, vector where)
Definition campaign.qc:191
string campaign_longdesc_wrapped[CAMPAIGN_MAX_ENTRIES]
Definition campaign.qc:6
void MultiCampaign_Next(entity btn, entity me)
Definition campaign.qc:142
void XonoticCampaignList_loadCvars(entity me)
Definition campaign.qc:69
void CampaignList_LoadMap(entity btn, entity me)
Definition campaign.qc:263
void XonoticCampaignList_configureXonoticCampaignList(entity me)
Definition campaign.qc:55
void XonoticCampaignList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
Definition campaign.qc:163
entity makeXonoticCampaignList()
Definition campaign.qc:48
float XonoticCampaignList_keyDown(entity me, float scan, float ascii, float shift)
Definition campaign.qc:276
void XonoticCampaignList_saveCvars(entity me)
Definition campaign.qc:89
void XonoticCampaignList_draw(entity me)
Definition campaign.qc:151
void XonoticCampaignList_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
Definition campaign.qc:195
void rewrapCampaign(float w, float l0, float emptyheight, vector theFontSize)
Definition campaign.qc:8
void XonoticCampaignList_destroy(entity me)
Definition campaign.qc:63
float getFadedAlpha(float currentAlpha, float startAlpha, float targetAlpha)
Definition util.qc:816
float registercvar(string name, string value, float flags)
float mod(float val, float m)
void cvar_set(string name, string value)
float bound(float min, float value, float max)
string substring(string s, float start, float length)
float cvar(string name)
string search_getfilename(float handle, float num)
const string cvar_string(string name)
float search_getsize(float handle)
float search_begin(string pattern, float caseinsensitive, float quiet)
float min(float f,...)
string ftos(float f)
const string cvar_defstring(string name)
string strzone(string s)
string argv(float n)
void search_end(float handle)
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define NEW(cname,...)
Definition oo.qh:117
#define SUPER(cname)
Definition oo.qh:231
vector
Definition self.qh:92
#define strfree(this)
Definition string.qh:59
#define strcpy(this, s)
Definition string.qh:52
const vector eY
Definition vector.qh:45
const vector eX
Definition vector.qh:44
#define vec3(_x, _y, _z)
Definition vector.qh:95