1#include "campaign.qh"
2#include "cheats.qh"
3#include "miscfunctions.qh"
4#include "g_world.qh"
5
6#include "../common/campaign_common.qh"
7
8// campaign cvars:
9//   _campaign_index: index of CURRENT map
10//   _campaign_name: name of the current campaign
11//   g_campaign(name)_index: index of current LAST map (saved)
12//   g_campaign_skill: bot skill offset
13
14float campaign_level;
15float campaign_won;
16string campaign_index_var;
17//float checkrules_equality;
18
19float CampaignBailout(string s)
20{
21	cvar = cvar_normal;
22	cvar_string = cvar_string_normal;
23	cvar_set = cvar_set_normal;
24	cvar_set("g_campaign", "0");
25	LOG_INFO("^4campaign initialization failed: ", s, "\n");
26	if(autocvar__campaign_testrun)
27		error("CAMPAIGN FAIL AHAHAHAHAHAHAHAHAH))");
28	return 1;
29}
30
31string cvar_campaignwrapper_list; // string of format ; var value; var value; var value;
32string cvar_string_campaignwrapper(string theCvar)
33{
34	float p, q;
35	p = strstrofs(cvar_campaignwrapper_list, strcat("; ", theCvar, " "), 0);
36	if(p < 0)
37		return cvar_defstring(theCvar);
38	p += strlen(theCvar) + 3;
39	q = strstrofs(cvar_campaignwrapper_list, ";", p);
40	if(q < 0)
41		return cvar_defstring(theCvar);
42	return substring(cvar_campaignwrapper_list, p, q - p);
43}
44float cvar_campaignwrapper(string theCvar)
45{
46	return stof(cvar_string_campaignwrapper(theCvar));
47}
48void cvar_set_campaignwrapper(string theCvar, string theValue)
49{
50	if(cvar_string_campaignwrapper(theCvar) == theValue)
51		return;
52	string s;
53	s = cvar_campaignwrapper_list;
54	cvar_campaignwrapper_list = strzone(strcat("; ", theCvar, " ", theValue, s));
55	strunzone(s);
56	//print(cvar_campaignwrapper_list, "\n");
57}
58
59float Campaign_Invalid()
60{
61	string thismapname, wantedmapname;
62	thismapname = GetMapname();
63	wantedmapname = campaign_gametype[0];
64	if(MapInfo_CurrentGametype() != MapInfo_Type_FromString(wantedmapname))
65		return CampaignBailout("wrong game type!");
66	wantedmapname = campaign_mapname[0];
67	if(wantedmapname != thismapname)
68		return CampaignBailout(strcat("wrong map: ", wantedmapname, " != ", thismapname));
69	return 0;
70}
71
72void CampaignPreInit()
73{
74	float baseskill;
75	string title;
76	campaign_level = autocvar__campaign_index;
77	campaign_name = strzone(autocvar__campaign_name);
78	campaign_index_var = strzone(strcat("g_campaign", campaign_name, "_index"));
79	CampaignFile_Load(campaign_level, 2);
80
81	if(campaign_entries < 1)
82	{
83		CampaignBailout("unknown map");
84		return;
85	}
86
87	if(autocvar_sv_cheats)
88	{
89		MapInfo_SwitchGameType(MapInfo_Type_FromString(campaign_gametype[0]));
90		CampaignFile_Unload();
91		CampaignBailout("JOLLY CHEATS AHAHAHAHAHAHAH))");
92		return;
93	}
94
95	baseskill = autocvar_g_campaign_skill;
96	baseskill = baseskill + campaign_botskill[0];
97	if(baseskill < 0)
98		baseskill = 0;
99
100	cvar_set("sv_public", "0");
101	cvar_set("pausable", "1");
102
103	cvar_campaignwrapper_list = strzone(strcat("; ", campaign_mutators[0], "; "));
104
105	cvar = cvar_campaignwrapper;
106	cvar_string = cvar_string_campaignwrapper;
107	cvar_set = cvar_set_campaignwrapper;
108
109	cvar_set("g_campaign", "1");
110	cvar_set("g_dm", "0");
111	cvar_set("skill", ftos(baseskill));
112	cvar_set("bot_number", ftos(campaign_bots[0]));
113	MapInfo_SwitchGameType(MapInfo_Type_FromString(campaign_gametype[0]));
114
115	// copy sv_gravity cvar, as the engine needs it too (sorry, this will mess
116	// with the menu a little still...)
117	cvar_set_normal("sv_gravity", ftos(autocvar_sv_gravity));
118
119	if(Campaign_Invalid())
120		return;
121
122	title = campaign_shortdesc[0];
123	title = strzone(strcat("Level ", ftos(campaign_level + 1), ": ", title));
124	campaign_message = strzone(strcat(title, "\n^3\n", campaign_longdesc[0], "\n\n^1press jump to enter the game"));
125	strunzone(title);
126}
127
128void CampaignPostInit()
129{
130	// now some sanity checks
131	if(Campaign_Invalid())
132		return;
133	if(autocvar__campaign_testrun)
134	{
135		cvar_set("fraglimit", "0");
136		cvar_set("timelimit", "0.01");
137		cvar_set_normal("fraglimit", "0");
138		cvar_set_normal("timelimit", "0.01");
139	}
140	else
141	{
142		cvar_set("fraglimit", ftos(campaign_fraglimit[0]));
143		cvar_set("timelimit", ftos(campaign_timelimit[0]));
144		cvar_set_normal("fraglimit", ftos(campaign_fraglimit[0]));
145		cvar_set_normal("timelimit", ftos(campaign_timelimit[0]));
146	}
147}
148
149void CampaignSaveCvar(string cvarname, float value)
150{
151	float fh;
152	float len;
153	string contents;
154	string l;
155
156	registercvar(cvarname, ftos(value));
157	cvar_set_normal(cvarname, ftos(value));
158	// note: cvarname must be remembered
159
160	fh = fopen("campaign.cfg", FILE_READ);
161	contents = "";
162	if(fh >= 0)
163	{
164		while((l = fgets(fh)))
165		{
166			len = tokenize_console(l);
167			if(len != 3)
168				continue;
169			if(argv(0) != "set")
170				continue;
171			if(argv(1) == cvarname)
172				continue;
173			contents = strcat(contents, "set ", argv(1), " ", argv(2), "\n");
174		}
175		fclose(fh);
176	}
177	contents = strcat(contents, "set ", cvarname,  " ", ftos(value), "\n");
178	fh = fopen("campaign.cfg", FILE_WRITE);
179	if(fh >= 0)
180	{
181		fputs(fh, contents);
182	}
183	else
184	{
185		error("Cannot write to campaign file");
186	}
187}
188
189void CampaignPreIntermission()
190{
191	int won = 0;
192	int lost = 0;
193	string savevar;
194
195	FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), LAMBDA(
196		if(it.winning)
197			won += 1;
198		else
199			lost += 1;
200	));
201
202	if(autocvar__campaign_testrun)
203	{
204		campaign_won = 1;
205		bprint("Campaign test run, advancing level.\n");
206	}
207	else if(won == 1 && lost == 0 && checkrules_equality == 0)
208	{
209		if(autocvar_timelimit != 0 && autocvar_fraglimit != 0 && time > autocvar_timelimit * 60) // checks if the timelimit has expired.
210		{
211			campaign_won = 0;
212			bprint("Time's up! The current level has been LOST.\n");
213			// sound!
214		}
215		else
216		{
217			campaign_won = 1;
218			bprint("The current level has been WON.\n");
219			// sound!
220		}
221	}
222	else if(autocvar_timelimit != 0 && time > autocvar_timelimit * 60)
223	{
224		campaign_won = 0;
225		bprint("Time's up! The current level has been LOST.\n");
226		// sound!
227	}
228	else
229	{
230		campaign_won = 0;
231		bprint("The current level has been LOST.\n");
232		// sound!
233	}
234
235	if(campaign_won && cheatcount_total == 0 && !autocvar__campaign_testrun)
236	{
237		if(campaign_level == cvar_normal(campaign_index_var))
238		{
239			if(campaign_entries < 2)
240			{
241				// I have won
242				savevar = strcat("g_campaign", campaign_name, "_won");
243				CampaignSaveCvar(savevar, 1);
244				// advance level (for menu to show it right)
245				CampaignSaveCvar(campaign_index_var, campaign_level + 1);
246			}
247			else
248			{
249				// advance level
250				CampaignSaveCvar(campaign_index_var, campaign_level + 1);
251			}
252		}
253	}
254}
255
256void CampaignPostIntermission()
257{
258	// NOTE: campaign_won is 0 or 1, that is, points to the next level
259
260	if(campaign_won && campaign_entries < 2)
261	{
262		// last map won!
263		LOG_DEBUG("^2test run: campaign looks GOOD");
264		localcmd("togglemenu 1\n");
265		CampaignFile_Unload();
266		return;
267	}
268
269	CampaignSetup(campaign_won);
270	CampaignFile_Unload();
271	strunzone(campaign_message);
272	strunzone(campaign_index_var);
273	strunzone(campaign_name);
274	campaign_name = "";
275}
276
277
278
279void CampaignLevelWarp(float n)
280{
281	if(n < 0)
282		n = campaign_level + 1;
283	CampaignFile_Unload();
284	CampaignFile_Load(n, 1);
285	if(campaign_entries)
286		CampaignSetup(0);
287	else
288		error("Sorry, cheater. You are NOT WELCOME.");
289	CampaignFile_Unload();
290}
291
292