1 //       _________ __                 __
2 //      /   _____//  |_____________ _/  |______     ____  __ __  ______
3 //      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
4 //      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ |
5 //     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
6 //             \/                  \/          \//_____/            \/
7 //  ______________________                           ______________________
8 //                        T H E   W A R   B E G I N S
9 //         Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name animation_setplayervar.cpp - The animation SetPlayerVar. */
12 //
13 //      (c) Copyright 2012 by Joris Dauphin
14 //
15 //      This program is free software; you can redistribute it and/or modify
16 //      it under the terms of the GNU General Public License as published by
17 //      the Free Software Foundation; only version 2 of the License.
18 //
19 //      This program is distributed in the hope that it will be useful,
20 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //      GNU General Public License for more details.
23 //
24 //      You should have received a copy of the GNU General Public License
25 //      along with this program; if not, write to the Free Software
26 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 //      02111-1307, USA.
28 //
29 
30 //@{
31 
32 /*----------------------------------------------------------------------------
33 --  Includes
34 ----------------------------------------------------------------------------*/
35 
36 #include "stratagus.h"
37 
38 #include "animation/animation_setplayervar.h"
39 
40 #include "animation.h"
41 #include "unit/unit.h"
42 
43 #include <stdio.h>
44 
45 /**
46 **  Gets the player data.
47 **
48 **  @param player  Player number.
49 **  @param prop    Player's property.
50 **  @param arg     Additional argument (for resource and unit).
51 **
52 **  @return  Returning value (only integer).
53 */
GetPlayerData(const int player,const char * prop,const char * arg)54 int GetPlayerData(const int player, const char *prop, const char *arg)
55 {
56 	if (!strcmp(prop, "RaceName")) {
57 		return Players[player].Race;
58 	} else if (!strcmp(prop, "Resources")) {
59 		const int resId = GetResourceIdByName(arg);
60 		if (resId == -1) {
61 			fprintf(stderr, "Invalid resource \"%s\"", arg);
62 			Exit(1);
63 		}
64 		return Players[player].Resources[resId] + Players[player].StoredResources[resId];
65 	} else if (!strcmp(prop, "StoredResources")) {
66 		const int resId = GetResourceIdByName(arg);
67 		if (resId == -1) {
68 			fprintf(stderr, "Invalid resource \"%s\"", arg);
69 			Exit(1);
70 		}
71 		return Players[player].StoredResources[resId];
72 	} else if (!strcmp(prop, "MaxResources")) {
73 		const int resId = GetResourceIdByName(arg);
74 		if (resId == -1) {
75 			fprintf(stderr, "Invalid resource \"%s\"", arg);
76 			Exit(1);
77 		}
78 		return Players[player].MaxResources[resId];
79 	} else if (!strcmp(prop, "Incomes")) {
80 		const int resId = GetResourceIdByName(arg);
81 		if (resId == -1) {
82 			fprintf(stderr, "Invalid resource \"%s\"", arg);
83 			Exit(1);
84 		}
85 		return Players[player].Incomes[resId];
86 	//Wyrmgus start
87 	} else if (!strcmp(prop, "Prices")) {
88 		const int resId = GetResourceIdByName(arg);
89 		if (resId == -1) {
90 			fprintf(stderr, "Invalid resource \"%s\"", arg);
91 			Exit(1);
92 		}
93 		return Players[player].GetResourcePrice(resId);
94 	} else if (!strcmp(prop, "ResourceDemand")) {
95 		const int resId = GetResourceIdByName(arg);
96 		if (resId == -1) {
97 			fprintf(stderr, "Invalid resource \"%s\"", arg);
98 			Exit(1);
99 		}
100 		return Players[player].ResourceDemand[resId];
101 	} else if (!strcmp(prop, "StoredResourceDemand")) {
102 		const int resId = GetResourceIdByName(arg);
103 		if (resId == -1) {
104 			fprintf(stderr, "Invalid resource \"%s\"", arg);
105 			Exit(1);
106 		}
107 		return Players[player].StoredResourceDemand[resId];
108 	} else if (!strcmp(prop, "EffectiveResourceDemand")) {
109 		const int resId = GetResourceIdByName(arg);
110 		if (resId == -1) {
111 			fprintf(stderr, "Invalid resource \"%s\"", arg);
112 			Exit(1);
113 		}
114 		return Players[player].GetEffectiveResourceDemand(resId);
115 	} else if (!strcmp(prop, "EffectiveResourceBuyPrice")) {
116 		const int resId = GetResourceIdByName(arg);
117 		if (resId == -1) {
118 			fprintf(stderr, "Invalid resource \"%s\"", arg);
119 			Exit(1);
120 		}
121 		return Players[player].GetEffectiveResourceBuyPrice(resId);
122 	} else if (!strcmp(prop, "EffectiveResourceSellPrice")) {
123 		const int resId = GetResourceIdByName(arg);
124 		if (resId == -1) {
125 			fprintf(stderr, "Invalid resource \"%s\"", arg);
126 			Exit(1);
127 		}
128 		return Players[player].GetEffectiveResourceSellPrice(resId);
129 	} else if (!strcmp(prop, "TradeCost")) {
130 		return Players[player].TradeCost;
131 	//Wyrmgus end
132 	} else if (!strcmp(prop, "UnitTypesCount")) {
133 		const std::string unit(arg);
134 		CUnitType *type = UnitTypeByIdent(unit);
135 		Assert(type);
136 		return Players[player].GetUnitTypeCount(type);
137 	} else if (!strcmp(prop, "UnitTypesUnderConstructionCount")) {
138 		const std::string unit(arg);
139 		CUnitType *type = UnitTypeByIdent(unit);
140 		Assert(type);
141 		return Players[player].GetUnitTypeUnderConstructionCount(type);
142 	} else if (!strcmp(prop, "UnitTypesAiActiveCount")) {
143 		const std::string unit(arg);
144 		CUnitType *type = UnitTypeByIdent(unit);
145 		Assert(type);
146 		return Players[player].GetUnitTypeAiActiveCount(type);
147 	} else if (!strcmp(prop, "AiEnabled")) {
148 		return Players[player].AiEnabled;
149 	} else if (!strcmp(prop, "TotalNumUnits")) {
150 		return Players[player].GetUnitCount();
151 	} else if (!strcmp(prop, "NumBuildings")) {
152 		return Players[player].NumBuildings;
153 	//Wyrmgus start
154 	} else if (!strcmp(prop, "NumBuildingsUnderConstruction")) {
155 		return Players[player].NumBuildingsUnderConstruction;
156 	//Wyrmgus end
157 	} else if (!strcmp(prop, "Supply")) {
158 		return Players[player].Supply;
159 	} else if (!strcmp(prop, "Demand")) {
160 		return Players[player].Demand;
161 	} else if (!strcmp(prop, "UnitLimit")) {
162 		return Players[player].UnitLimit;
163 	} else if (!strcmp(prop, "BuildingLimit")) {
164 		return Players[player].BuildingLimit;
165 	} else if (!strcmp(prop, "TotalUnitLimit")) {
166 		return Players[player].TotalUnitLimit;
167 	} else if (!strcmp(prop, "Score")) {
168 		return Players[player].Score;
169 	} else if (!strcmp(prop, "TotalUnits")) {
170 		return Players[player].TotalUnits;
171 	} else if (!strcmp(prop, "TotalBuildings")) {
172 		return Players[player].TotalBuildings;
173 	} else if (!strcmp(prop, "TotalResources")) {
174 		const int resId = GetResourceIdByName(arg);
175 		if (resId == -1) {
176 			fprintf(stderr, "Invalid resource \"%s\"", arg);
177 			Exit(1);
178 		}
179 		return Players[player].TotalResources[resId];
180 	} else if (!strcmp(prop, "TotalRazings")) {
181 		return Players[player].TotalRazings;
182 	} else if (!strcmp(prop, "TotalKills")) {
183 		return Players[player].TotalKills;
184 	} else {
185 		fprintf(stderr, "Invalid field: %s" _C_ prop);
186 		Exit(1);
187 	}
188 	return 0;
189 }
190 
191 /**
192 **  Sets the player data.
193 */
SetPlayerData(const int player,const char * prop,const char * arg,int value)194 static void SetPlayerData(const int player, const char *prop, const char *arg, int value)
195 {
196 	if (!strcmp(prop, "RaceName")) {
197 		//Wyrmgus start
198 //		Players[player].Race = value;
199 		Players[player].SetCivilization(value);
200 		//Wyrmgus end
201 	} else if (!strcmp(prop, "Resources")) {
202 		const int resId = GetResourceIdByName(arg);
203 		if (resId == -1) {
204 			fprintf(stderr, "Invalid resource \"%s\"", arg);
205 			Exit(1);
206 		}
207 		Players[player].SetResource(resId, value, STORE_BOTH);
208 	} else if (!strcmp(prop, "StoredResources")) {
209 		const int resId = GetResourceIdByName(arg);
210 		if (resId == -1) {
211 			fprintf(stderr, "Invalid resource \"%s\"", arg);
212 			Exit(1);
213 		}
214 		Players[player].SetResource(resId, value, STORE_BUILDING);
215 	} else if (!strcmp(prop, "UnitLimit")) {
216 		Players[player].UnitLimit = value;
217 	} else if (!strcmp(prop, "BuildingLimit")) {
218 		Players[player].BuildingLimit = value;
219 	} else if (!strcmp(prop, "TotalUnitLimit")) {
220 		Players[player].TotalUnitLimit = value;
221 	} else if (!strcmp(prop, "Score")) {
222 		Players[player].Score = value;
223 	} else if (!strcmp(prop, "TotalUnits")) {
224 		Players[player].TotalUnits = value;
225 	} else if (!strcmp(prop, "TotalBuildings")) {
226 		Players[player].TotalBuildings = value;
227 	} else if (!strcmp(prop, "TotalResources")) {
228 		const int resId = GetResourceIdByName(arg);
229 		if (resId == -1) {
230 			fprintf(stderr, "Invalid resource \"%s\"", arg);
231 			Exit(1);
232 		}
233 		Players[player].TotalResources[resId] = value;
234 	} else if (!strcmp(prop, "TotalRazings")) {
235 		Players[player].TotalRazings = value;
236 	} else if (!strcmp(prop, "TotalKills")) {
237 		Players[player].TotalKills = value;
238 	} else {
239 		fprintf(stderr, "Invalid field: %s" _C_ prop);
240 		Exit(1);
241 	}
242 }
243 
244 
Action(CUnit & unit,int &,int) const245 /* virtual */ void CAnimation_SetPlayerVar::Action(CUnit &unit, int &/*move*/, int /*scale*/) const
246 {
247 	Assert(unit.Anim.Anim == this);
248 
249 	const char *var = this->varStr.c_str();
250 	const char *arg = this->argStr.c_str();
251 	const int playerId = ParseAnimInt(unit, this->playerStr.c_str());
252 	int rop = ParseAnimInt(unit, this->valueStr.c_str());
253 	int data = GetPlayerData(playerId, var, arg);
254 
255 	switch (this->mod) {
256 		case modAdd:
257 			data += rop;
258 			break;
259 		case modSub:
260 			data -= rop;
261 			break;
262 		case modMul:
263 			data *= rop;
264 			break;
265 		case modDiv:
266 			if (!rop) {
267 				fprintf(stderr, "Division by zero in AnimationSetPlayerVar\n");
268 				Exit(1);
269 			}
270 			data /= rop;
271 			break;
272 		case modMod:
273 			if (!rop) {
274 				fprintf(stderr, "Division by zero in AnimationSetPlayerVar\n");
275 				Exit(1);
276 			}
277 			data %= rop;
278 			break;
279 		case modAnd:
280 			data &= rop;
281 			break;
282 		case modOr:
283 			data |= rop;
284 			break;
285 		case modXor:
286 			data ^= rop;
287 			break;
288 		case modNot:
289 			data = !data;
290 			break;
291 		default:
292 			data = rop;
293 	}
294 	rop = data;
295 	SetPlayerData(playerId, var, arg, rop);
296 }
297 
298 /*
299 **  s = "player var mod value [arg2]"
300 */
Init(const char * s,lua_State *)301 /* virtual */ void CAnimation_SetPlayerVar::Init(const char *s, lua_State *)
302 {
303 	const std::string str(s);
304 	const size_t len = str.size();
305 
306 	size_t begin = 0;
307 	size_t end = str.find(' ', begin);
308 	this->playerStr.assign(str, begin, end - begin);
309 
310 	begin = std::min(len, str.find_first_not_of(' ', end));
311 	end = std::min(len, str.find(' ', begin));
312 	this->varStr.assign(str, begin, end - begin);
313 
314 	begin = std::min(len, str.find_first_not_of(' ', end));
315 	end = std::min(len, str.find(' ', begin));
316 	const std::string modStr(str, begin, end - begin);
317 	if (modStr == "=") {
318 		this->mod = modSet;
319 	} else if (modStr == "+=") {
320 		this->mod = modAdd;
321 	} else if (modStr == "-=") {
322 		this->mod = modSub;
323 	} else if (modStr == "*=") {
324 		this->mod = modMul;
325 	} else if (modStr == "/=") {
326 		this->mod = modDiv;
327 	} else if (modStr == "%=") {
328 		this->mod = modMod;
329 	} else if (modStr == "&=") {
330 		this->mod = modAnd;
331 	} else if (modStr == "|=") {
332 		this->mod = modOr;
333 	} else if (modStr == "^=") {
334 		this->mod = modXor;
335 	} else if (modStr == "!") {
336 		this->mod = modNot;
337 	} else {
338 		this->mod = (SetVar_ModifyTypes)(atoi(modStr.c_str()));
339 	}
340 
341 	begin = std::min(len, str.find_first_not_of(' ', end));
342 	end = std::min(len, str.find(' ', begin));
343 	this->valueStr.assign(str, begin, end - begin);
344 
345 	begin = std::min(len, str.find_first_not_of(' ', end));
346 	end = std::min(len, str.find(' ', begin));
347 	this->argStr.assign(str, begin, end - begin);
348 }
349 
350 //@}
351