1 /* GemRB - Infinity Engine Emulator
2  * Copyright (C) 2003 The GemRB Project
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  *
19  */
20 
21 #include "GameScript/GameScript.h"
22 
23 #include "GameScript/GSUtils.h"
24 #include "GameScript/Matching.h"
25 
26 #include "DialogHandler.h"
27 #include "Game.h"
28 #include "GUI/GameControl.h"
29 
30 namespace GemRB {
31 
32 //-------------------------------------------------------------
33 // Object Functions
34 //-------------------------------------------------------------
35 
36 //in this implementation, Myself will drop the parameter array
37 //i think all object filters could be expected to do so
38 //they should remove unnecessary elements from the parameters
Myself(const Scriptable * Sender,Targets * parameters,int ga_flags)39 Targets *GameScript::Myself(const Scriptable *Sender, Targets* parameters, int ga_flags)
40 {
41 	parameters->Clear();
42 	// hack to allow all Object methods to take a const Scriptable
43 	Scriptable *snd;
44 	Map *ca = Sender->GetCurrentArea();
45 	if (ca) {
46 		snd = ca->GetScriptableByGlobalID(Sender->GetGlobalID());
47 	} else {
48 		// just in case we're in the middle of a move
49 		snd = core->GetGame()->GetActorByGlobalID(Sender->GetGlobalID());
50 	}
51 	parameters->AddTarget(snd, 0, ga_flags);
52 	return parameters;
53 }
54 
NearestDoor(const Scriptable *,Targets * parameters,int)55 Targets *GameScript::NearestDoor(const Scriptable */*Sender*/, Targets *parameters, int /*ga_flags*/)
56 {
57 	return XthNearestDoor(parameters, 0);
58 }
59 
SecondNearestDoor(const Scriptable *,Targets * parameters,int)60 Targets *GameScript::SecondNearestDoor(const Scriptable */*Sender*/, Targets *parameters, int /*ga_flags*/)
61 {
62 	return XthNearestDoor(parameters, 1);
63 }
64 
ThirdNearestDoor(const Scriptable *,Targets * parameters,int)65 Targets *GameScript::ThirdNearestDoor(const Scriptable */*Sender*/, Targets *parameters, int /*ga_flags*/)
66 {
67 	return XthNearestDoor(parameters, 2);
68 }
69 
FourthNearestDoor(const Scriptable *,Targets * parameters,int)70 Targets *GameScript::FourthNearestDoor(const Scriptable */*Sender*/, Targets *parameters, int /*ga_flags*/)
71 {
72 	return XthNearestDoor(parameters, 3);
73 }
74 
FifthNearestDoor(const Scriptable *,Targets * parameters,int)75 Targets *GameScript::FifthNearestDoor(const Scriptable */*Sender*/, Targets *parameters, int /*ga_flags*/)
76 {
77 	return XthNearestDoor(parameters, 4);
78 }
79 
SixthNearestDoor(const Scriptable *,Targets * parameters,int)80 Targets *GameScript::SixthNearestDoor(const Scriptable */*Sender*/, Targets *parameters, int /*ga_flags*/)
81 {
82 	return XthNearestDoor(parameters, 5);
83 }
84 
SeventhNearestDoor(const Scriptable *,Targets * parameters,int)85 Targets *GameScript::SeventhNearestDoor(const Scriptable */*Sender*/, Targets *parameters, int /*ga_flags*/)
86 {
87 	return XthNearestDoor(parameters, 6);
88 }
89 
EighthNearestDoor(const Scriptable *,Targets * parameters,int)90 Targets *GameScript::EighthNearestDoor(const Scriptable */*Sender*/, Targets *parameters, int /*ga_flags*/)
91 {
92 	return XthNearestDoor(parameters, 7);
93 }
94 
NinthNearestDoor(const Scriptable *,Targets * parameters,int)95 Targets *GameScript::NinthNearestDoor(const Scriptable */*Sender*/, Targets *parameters, int /*ga_flags*/)
96 {
97 	return XthNearestDoor(parameters, 8);
98 }
99 
TenthNearestDoor(const Scriptable *,Targets * parameters,int)100 Targets *GameScript::TenthNearestDoor(const Scriptable */*Sender*/, Targets *parameters, int /*ga_flags*/)
101 {
102 	return XthNearestDoor(parameters, 9);
103 }
104 
105 //in bg2 it is same as player1 so far
106 //in iwd2 this is the Gabber!!!
107 //but also, if there is no gabber, it is the first PC
108 //probably it is simply the nearest exportable character...
Protagonist(const Scriptable * Sender,Targets * parameters,int ga_flags)109 Targets *GameScript::Protagonist(const Scriptable *Sender, Targets *parameters, int ga_flags)
110 {
111 	parameters->Clear();
112 	//this sucks but IWD2 is like that...
113 	static bool charnameisgabber = core->HasFeature(GF_CHARNAMEISGABBER);
114 	if (charnameisgabber) {
115 		const GameControl* gc = core->GetGameControl();
116 		if (gc) {
117 			parameters->AddTarget(gc->dialoghandler->GetSpeaker(), 0, ga_flags);
118 		}
119 		if (parameters->Count()) {
120 			return parameters;
121 		}
122 		//ok, this will return the nearest PC in the first slot
123 		const Game *game = core->GetGame();
124 		int i = game->GetPartySize(false);
125 		while(i--) {
126 			Actor *target = game->GetPC(i,false);
127 			parameters->AddTarget(target, Distance(Sender, target), ga_flags);
128 		}
129 		return parameters;
130 	}
131 	parameters->AddTarget(core->GetGame()->GetPC(0, false), 0, ga_flags);
132 	return parameters;
133 }
134 
135 //last talker
Gabber(const Scriptable *,Targets * parameters,int ga_flags)136 Targets *GameScript::Gabber(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
137 {
138 	parameters->Clear();
139 	const GameControl *gc = core->GetGameControl();
140 	if (gc) {
141 		parameters->AddTarget(gc->dialoghandler->GetSpeaker(), 0, ga_flags);
142 	}
143 	return parameters;
144 }
145 
LastTrigger(const Scriptable * Sender,Targets * parameters,int ga_flags)146 Targets *GameScript::LastTrigger(const Scriptable *Sender, Targets *parameters, int ga_flags)
147 {
148 	Scriptable *target = parameters->GetTarget(0, -1);
149 	parameters->Clear();
150 	if (target) {
151 		target = Sender->GetCurrentArea()->GetActorByGlobalID(target->LastTrigger);
152 		parameters->AddTarget(target, 0, ga_flags);
153 	} else if (Sender->LastTrigger) {
154 		target = Sender->GetCurrentArea()->GetActorByGlobalID(Sender->LastTrigger);
155 		parameters->AddTarget(target, 0, ga_flags);
156 	}
157 	return parameters;
158 }
159 
LastMarkedObject(const Scriptable * Sender,Targets * parameters,int ga_flags)160 Targets *GameScript::LastMarkedObject(const Scriptable *Sender, Targets *parameters, int ga_flags)
161 {
162 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
163 	if (!actor) {
164 		if (Sender->Type==ST_ACTOR) {
165 			actor = (const Actor *) Sender;
166 		}
167 	}
168 	parameters->Clear();
169 	if (actor) {
170 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastMarked);
171 		if (target) {
172 			parameters->AddTarget(target, 0, ga_flags);
173 		}
174 	}
175 	return parameters;
176 }
177 
SpellTarget(const Scriptable * Sender,Targets * parameters,int ga_flags)178 Targets *GameScript::SpellTarget(const Scriptable *Sender, Targets *parameters, int ga_flags)
179 {
180 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
181 	if (!actor) {
182 		if (Sender->Type==ST_ACTOR) {
183 			actor = (const Actor *) Sender;
184 		}
185 	}
186 	parameters->Clear();
187 	if (actor) {
188 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastSpellTarget);
189 		if (target) {
190 			parameters->AddTarget(target, 0, ga_flags);
191 		}
192 	}
193 	return parameters;
194 }
195 
196 //actions should always use LastMarkedObject, because LastSeen could be deleted
LastSeenBy(const Scriptable * Sender,Targets * parameters,int ga_flags)197 Targets *GameScript::LastSeenBy(const Scriptable *Sender, Targets *parameters, int ga_flags)
198 {
199 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
200 	if (!actor) {
201 		if (Sender->Type==ST_ACTOR) {
202 			actor = (const Actor *) Sender;
203 		}
204 	}
205 	parameters->Clear();
206 	if (actor) {
207 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastSeen);
208 		if (target) {
209 			parameters->AddTarget(target, 0, ga_flags);
210 		}
211 	}
212 	return parameters;
213 }
214 
LastHelp(const Scriptable * Sender,Targets * parameters,int ga_flags)215 Targets *GameScript::LastHelp(const Scriptable *Sender, Targets *parameters, int ga_flags)
216 {
217 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
218 	if (!actor) {
219 		if (Sender->Type==ST_ACTOR) {
220 			actor = (const Actor *) Sender;
221 		}
222 	}
223 	parameters->Clear();
224 	if (actor) {
225 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastHelp);
226 		if (target) {
227 			parameters->AddTarget(target, 0, ga_flags);
228 		}
229 	}
230 	return parameters;
231 }
232 
LastHeardBy(const Scriptable * Sender,Targets * parameters,int ga_flags)233 Targets *GameScript::LastHeardBy(const Scriptable *Sender, Targets *parameters, int ga_flags)
234 {
235 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
236 	if (!actor) {
237 		if (Sender->Type==ST_ACTOR) {
238 			actor = (const Actor *) Sender;
239 		}
240 	}
241 	parameters->Clear();
242 	if (actor) {
243 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastHeard);
244 		if (target) {
245 			parameters->AddTarget(target, 0, ga_flags);
246 		}
247 	}
248 	return parameters;
249 }
250 
251 //i was told that Group means the same specifics, so this is just an
252 //object selector for everyone with the same specifics as the current object
GroupOf(const Scriptable * Sender,Targets * parameters,int ga_flags)253 Targets *GameScript::GroupOf(const Scriptable *Sender, Targets *parameters, int ga_flags)
254 {
255 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
256 	if (!actor) {
257 		if (Sender->Type==ST_ACTOR) {
258 			actor = (const Actor *) Sender;
259 		}
260 	}
261 	parameters->Clear();
262 	if (actor) {
263 		ieDword tmp = actor->GetStat(IE_SPECIFIC);
264 		const Map *cm = Sender->GetCurrentArea();
265 		int i = cm->GetActorCount(true);
266 		while (i--) {
267 			Actor *target=cm->GetActor(i,true);
268 			if (target && (target->GetStat(IE_SPECIFIC)==tmp) ) {
269 				parameters->AddTarget(target, 0, ga_flags);
270 			}
271 		}
272 	}
273 	return parameters;
274 }
275 
276 /*this one is tough, but done */
ProtectorOf(const Scriptable * Sender,Targets * parameters,int ga_flags)277 Targets *GameScript::ProtectorOf(const Scriptable *Sender, Targets *parameters, int ga_flags)
278 {
279 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
280 	if (!actor) {
281 		if (Sender->Type==ST_ACTOR) {
282 			actor = (const Actor *) Sender;
283 		}
284 	}
285 	parameters->Clear();
286 	/*if (actor) {
287 		ieWord tmp = actor->LastProtected;
288 		Map *cm = Sender->GetCurrentArea();
289 		int i = cm->GetActorCount(true);
290 		while (i--) {
291 			Actor *target=cm->GetActor(i,true);
292 			if (target && (target->LastProtected ==tmp) ) {
293 				parameters->AddTarget(target, 0, ga_flags);
294 			}
295 		}
296 	}*/
297 	if (actor) {
298 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastProtector);
299 		if (target) {
300 			parameters->AddTarget(target, 0, ga_flags);
301 		}
302 	}
303 	return parameters;
304 }
305 
ProtectedBy(const Scriptable * Sender,Targets * parameters,int ga_flags)306 Targets *GameScript::ProtectedBy(const Scriptable *Sender, Targets *parameters, int ga_flags)
307 {
308 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
309 	if (!actor) {
310 		if (Sender->Type==ST_ACTOR) {
311 			actor = (const Actor *) Sender;
312 		}
313 	}
314 	parameters->Clear();
315 	if (actor) {
316 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastProtectee);
317 		if (target) {
318 			parameters->AddTarget(target, 0, ga_flags);
319 		}
320 	}
321 	return parameters;
322 }
323 
LastCommandedBy(const Scriptable * Sender,Targets * parameters,int ga_flags)324 Targets *GameScript::LastCommandedBy(const Scriptable *Sender, Targets *parameters, int ga_flags)
325 {
326 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
327 	if (!actor) {
328 		if (Sender->Type==ST_ACTOR) {
329 			actor = (const Actor *) Sender;
330 		}
331 	}
332 	parameters->Clear();
333 	if (actor) {
334 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastCommander);
335 		if (target) {
336 			parameters->AddTarget(target, 0, ga_flags);
337 		}
338 	}
339 	return parameters;
340 }
341 
342 // this is essentially a LastTargetedBy(0) - or MySelf
343 // but IWD2 defines it
MyTarget(const Scriptable * Sender,Targets * parameters,int ga_flags)344 Targets *GameScript::MyTarget(const Scriptable *Sender, Targets *parameters, int ga_flags)
345 {
346 	const Scriptable *actor = parameters->GetTarget(0, -1);
347 	if (!actor) {
348 		actor = Sender;
349 	}
350 	parameters->Clear();
351 	if (actor) {
352 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->MyTarget);
353 		if (target) {
354 			parameters->AddTarget(target, 0, ga_flags);
355 		}
356 	}
357 	return parameters;
358 }
359 
LastTargetedBy(const Scriptable * Sender,Targets * parameters,int ga_flags)360 Targets *GameScript::LastTargetedBy(const Scriptable *Sender, Targets *parameters, int ga_flags)
361 {
362 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
363 	return GetMyTarget(Sender, actor, parameters, ga_flags);
364 }
365 
LastAttackerOf(const Scriptable * Sender,Targets * parameters,int ga_flags)366 Targets *GameScript::LastAttackerOf(const Scriptable *Sender, Targets *parameters, int ga_flags)
367 {
368 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
369 	if (!actor) {
370 		if (Sender->Type==ST_ACTOR) {
371 			actor = (const Actor *) Sender;
372 		}
373 	}
374 	parameters->Clear();
375 	if (actor) {
376 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastAttacker);
377 		if (target) {
378 			parameters->AddTarget(target, 0, ga_flags);
379 		}
380 	}
381 	return parameters;
382 }
383 
LastHitter(const Scriptable * Sender,Targets * parameters,int ga_flags)384 Targets *GameScript::LastHitter(const Scriptable *Sender, Targets *parameters, int ga_flags)
385 {
386 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
387 	if (!actor) {
388 		if (Sender->Type==ST_ACTOR) {
389 			actor = (const Actor *) Sender;
390 		}
391 	}
392 	parameters->Clear();
393 	if (actor) {
394 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastHitter);
395 		if (target) {
396 			parameters->AddTarget(target, 0, ga_flags);
397 		}
398 	}
399 	return parameters;
400 }
401 
LeaderOf(const Scriptable * Sender,Targets * parameters,int ga_flags)402 Targets *GameScript::LeaderOf(const Scriptable *Sender, Targets *parameters, int ga_flags)
403 {
404 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
405 	if (!actor) {
406 		if (Sender->Type==ST_ACTOR) {
407 			actor = (const Actor *) Sender;
408 		}
409 	}
410 	parameters->Clear();
411 	if (actor) {
412 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastFollowed);
413 		if (target) {
414 			parameters->AddTarget(target, 0, ga_flags);
415 		}
416 	}
417 	return parameters;
418 }
419 
LastTalkedToBy(const Scriptable * Sender,Targets * parameters,int ga_flags)420 Targets *GameScript::LastTalkedToBy(const Scriptable *Sender, Targets *parameters, int ga_flags)
421 {
422 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
423 	if (!actor) {
424 		if (Sender->Type==ST_ACTOR) {
425 			actor = (const Actor *) Sender;
426 		}
427 	}
428 	parameters->Clear();
429 	if (actor) {
430 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastTalker);
431 		if (target) {
432 			parameters->AddTarget(target, 0, ga_flags);
433 		}
434 	}
435 	return parameters;
436 }
437 
LastSummonerOf(const Scriptable * Sender,Targets * parameters,int ga_flags)438 Targets *GameScript::LastSummonerOf(const Scriptable *Sender, Targets *parameters, int ga_flags)
439 {
440 	const Actor *actor = (Actor *) parameters->GetTarget(0, ST_ACTOR);
441 	if (!actor) {
442 		if (Sender->Type==ST_ACTOR) {
443 			actor = (const Actor *) Sender;
444 		}
445 	}
446 	parameters->Clear();
447 	if (actor) {
448 		Actor *target = actor->GetCurrentArea()->GetActorByGlobalID(actor->LastSummoner);
449 		if (target) {
450 			parameters->AddTarget(target, 0, ga_flags);
451 		}
452 	}
453 	return parameters;
454 }
455 
PlayerX(Targets * parameters,int ga_flags,unsigned int slot,bool fill=false)456 inline Targets *PlayerX(Targets *parameters, int ga_flags, unsigned int slot, bool fill = false)
457 {
458 	parameters->Clear();
459 	Actor *pc;
460 	if (fill) {
461 		pc = core->GetGame()->FindPC(slot + 1);
462 	} else {
463 		pc = core->GetGame()->GetPC(slot, false);
464 	}
465 	parameters->AddTarget(pc, 0, ga_flags);
466 	return parameters;
467 }
468 
Player1(const Scriptable *,Targets * parameters,int ga_flags)469 Targets *GameScript::Player1(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
470 {
471 	return PlayerX(parameters, ga_flags, 0);
472 }
473 
Player1Fill(const Scriptable *,Targets * parameters,int ga_flags)474 Targets *GameScript::Player1Fill(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
475 {
476 	return PlayerX(parameters, ga_flags, 0, true);
477 }
478 
Player2(const Scriptable *,Targets * parameters,int ga_flags)479 Targets *GameScript::Player2(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
480 {
481 	return PlayerX(parameters, ga_flags, 1);
482 }
483 
Player2Fill(const Scriptable *,Targets * parameters,int ga_flags)484 Targets *GameScript::Player2Fill(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
485 {
486 	return PlayerX(parameters, ga_flags, 1, true);
487 }
488 
Player3(const Scriptable *,Targets * parameters,int ga_flags)489 Targets *GameScript::Player3(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
490 {
491 	return PlayerX(parameters, ga_flags, 2);
492 }
493 
Player3Fill(const Scriptable *,Targets * parameters,int ga_flags)494 Targets *GameScript::Player3Fill(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
495 {
496 	return PlayerX(parameters, ga_flags, 2, true);
497 }
498 
Player4(const Scriptable *,Targets * parameters,int ga_flags)499 Targets *GameScript::Player4(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
500 {
501 	return PlayerX(parameters, ga_flags, 3);
502 }
503 
Player4Fill(const Scriptable *,Targets * parameters,int ga_flags)504 Targets *GameScript::Player4Fill(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
505 {
506 	return PlayerX(parameters, ga_flags, 3, true);
507 }
508 
Player5(const Scriptable *,Targets * parameters,int ga_flags)509 Targets *GameScript::Player5(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
510 {
511 	return PlayerX(parameters, ga_flags, 4);
512 }
513 
Player5Fill(const Scriptable *,Targets * parameters,int ga_flags)514 Targets *GameScript::Player5Fill(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
515 {
516 	return PlayerX(parameters, ga_flags, 4, true);
517 }
518 
Player6(const Scriptable *,Targets * parameters,int ga_flags)519 Targets *GameScript::Player6(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
520 {
521 	return PlayerX(parameters, ga_flags, 5);
522 }
523 
Player6Fill(const Scriptable *,Targets * parameters,int ga_flags)524 Targets *GameScript::Player6Fill(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
525 {
526 	return PlayerX(parameters, ga_flags, 5, true);
527 }
528 
Player7(const Scriptable *,Targets * parameters,int ga_flags)529 Targets *GameScript::Player7(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
530 {
531 	return PlayerX(parameters, ga_flags, 6);
532 }
533 
Player7Fill(const Scriptable *,Targets * parameters,int ga_flags)534 Targets *GameScript::Player7Fill(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
535 {
536 	return PlayerX(parameters, ga_flags, 6, true);
537 }
538 
Player8(const Scriptable *,Targets * parameters,int ga_flags)539 Targets *GameScript::Player8(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
540 {
541 	return PlayerX(parameters, ga_flags, 7);
542 }
543 
Player8Fill(const Scriptable *,Targets * parameters,int ga_flags)544 Targets *GameScript::Player8Fill(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
545 {
546 	return PlayerX(parameters, ga_flags, 7, true);
547 }
548 
Player9(const Scriptable *,Targets * parameters,int ga_flags)549 Targets *GameScript::Player9(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
550 {
551 	return PlayerX(parameters, ga_flags, 8);
552 }
553 
Player9Fill(const Scriptable *,Targets * parameters,int ga_flags)554 Targets *GameScript::Player9Fill(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
555 {
556 	return PlayerX(parameters, ga_flags, 8, true);
557 }
558 
Player10(const Scriptable *,Targets * parameters,int ga_flags)559 Targets *GameScript::Player10(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
560 {
561 	return PlayerX(parameters, ga_flags, 9);
562 }
563 
Player10Fill(const Scriptable *,Targets * parameters,int ga_flags)564 Targets *GameScript::Player10Fill(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
565 {
566 	return PlayerX(parameters, ga_flags, 9, true);
567 }
568 
569 //This filter works only on the Party - silly restriction, but the dataset expects this
StrongestOfMale(const Scriptable * Sender,Targets * parameters,int ga_flags)570 Targets *GameScript::StrongestOfMale(const Scriptable *Sender, Targets *parameters, int ga_flags)
571 {
572 	const Map *area = Sender->GetCurrentArea();
573 	const Game *game = core->GetGame();
574 	Scriptable* scr = NULL;
575 	int besthp = 0;
576 	int i = game->GetPartySize(false);
577 	while (i--) {
578 		Actor *actor = game->GetPC(i, false);
579 		if (actor->GetStat(IE_SEX)!=SEX_MALE) continue;
580 		if(actor->GetCurrentArea() == area) {
581 			int hp = actor->GetStat(IE_HITPOINTS);
582 			if (!scr || besthp<hp) {
583 				besthp=hp;
584 				scr=actor;
585 			}
586 		}
587 	}
588 	parameters->Clear();
589 	parameters->AddTarget(scr, 0, ga_flags);
590 	return parameters;
591 }
592 
593 //This filter works only on the Party - silly restriction, but the dataset expects this
StrongestOf(const Scriptable * Sender,Targets * parameters,int ga_flags)594 Targets *GameScript::StrongestOf(const Scriptable *Sender, Targets *parameters, int ga_flags)
595 {
596 	const Map *area = Sender->GetCurrentArea();
597 	const Game *game = core->GetGame();
598 	Scriptable* scr = NULL;
599 	int besthp = 0;
600 	int i = game->GetPartySize(false);
601 	while (i--) {
602 		Actor *actor = game->GetPC(i, false);
603 		if(actor->GetCurrentArea() == area) {
604 			int hp = actor->GetStat(IE_HITPOINTS);
605 			if (!scr || besthp<hp) {
606 				besthp=hp;
607 				scr=actor;
608 			}
609 		}
610 	}
611 	parameters->Clear();
612 	parameters->AddTarget(scr, 0, ga_flags);
613 	return parameters;
614 }
615 
616 //This filter works only on the Party - silly restriction, but the dataset expects this
WeakestOf(const Scriptable * Sender,Targets * parameters,int ga_flags)617 Targets *GameScript::WeakestOf(const Scriptable *Sender, Targets *parameters, int ga_flags)
618 {
619 	const Map *area = Sender->GetCurrentArea();
620 	const Game *game = core->GetGame();
621 	Scriptable* scr = NULL;
622 	int worsthp = 0;
623 	int i = game->GetPartySize(false);
624 	while (i--) {
625 		Actor *actor = game->GetPC(i, false);
626 		if(actor->GetCurrentArea() == area) {
627 			int hp = actor->GetStat(IE_HITPOINTS);
628 			if (!scr || worsthp>hp) {
629 				worsthp=hp;
630 				scr=actor;
631 			}
632 		}
633 	}
634 	parameters->Clear();
635 	parameters->AddTarget(scr, 0, ga_flags);
636 	return parameters;
637 }
638 
639 //This filter works only on the Party - silly restriction, but the dataset expects this
BestAC(const Scriptable * Sender,Targets * parameters,int ga_flags)640 Targets *GameScript::BestAC(const Scriptable *Sender, Targets *parameters, int ga_flags)
641 {
642 	const Map *area = Sender->GetCurrentArea();
643 	const Game *game = core->GetGame();
644 	Scriptable* scr = NULL;
645 	int bestac = 0;
646 	int i = game->GetPartySize(false);
647 	while (i--) {
648 		Actor *actor = game->GetPC(i, false);
649 		if(actor->GetCurrentArea() == area) {
650 			int ac = actor->AC.GetTotal();
651 			if (!scr || bestac>ac) {
652 				bestac=ac;
653 				scr=actor;
654 			}
655 		}
656 	}
657 	parameters->Clear();
658 	parameters->AddTarget(scr, 0, ga_flags);
659 	return parameters;
660 }
661 
662 //This filter works only on the Party - silly restriction, but the dataset expects this
WorstAC(const Scriptable * Sender,Targets * parameters,int ga_flags)663 Targets *GameScript::WorstAC(const Scriptable *Sender, Targets *parameters, int ga_flags)
664 {
665 	const Map *area = Sender->GetCurrentArea();
666 	const Game *game = core->GetGame();
667 	Scriptable* scr = NULL;
668 	int worstac = 0;
669 	int i = game->GetPartySize(false);
670 	while (i--) {
671 		Actor *actor = game->GetPC(i, false);
672 		if(actor->GetCurrentArea() == area) {
673 			int ac = actor->AC.GetTotal();
674 			if (!scr || worstac<ac) {
675 				worstac=ac;
676 				scr=actor;
677 			}
678 		}
679 	}
680 	parameters->Clear();
681 	parameters->AddTarget(scr, 0, ga_flags);
682 	return parameters;
683 }
684 
685 //This filter works only on the Party - silly restriction, but the dataset expects this
MostDamagedOf(const Scriptable * Sender,Targets * parameters,int ga_flags)686 Targets *GameScript::MostDamagedOf(const Scriptable *Sender, Targets *parameters, int ga_flags)
687 {
688 	const Map *area = Sender->GetCurrentArea();
689 	const Game *game = core->GetGame();
690 	Scriptable* scr = NULL;
691 	int worsthp = 0;
692 	int i = game->GetPartySize(false);
693 	while (i--) {
694 		Actor *actor = game->GetPC(i, false);
695 		if(actor->GetCurrentArea() == area) {
696 			int hp=actor->GetStat(IE_MAXHITPOINTS)-actor->GetBase(IE_HITPOINTS);
697 			if (!scr || hp>worsthp) {
698 				worsthp=hp;
699 				scr=actor;
700 			}
701 		}
702 	}
703 	parameters->Clear();
704 	parameters->AddTarget(scr, 0, ga_flags);
705 	return parameters;
706 }
707 
708 //This filter works only on the Party - silly restriction, but the dataset expects this
709 //For example the beholder01 script
LeastDamagedOf(const Scriptable * Sender,Targets * parameters,int ga_flags)710 Targets *GameScript::LeastDamagedOf(const Scriptable *Sender, Targets *parameters, int ga_flags)
711 {
712 	const Map *area = Sender->GetCurrentArea();
713 	const Game *game = core->GetGame();
714 	Scriptable* scr = NULL;
715 	int besthp = 0;
716 	int i = game->GetPartySize(false);
717 	while (i--) {
718 		Actor *actor = game->GetPC(i, false);
719 		if(actor->GetCurrentArea() == area) {
720 			int hp=actor->GetStat(IE_MAXHITPOINTS)-actor->GetBase(IE_HITPOINTS);
721 			if (!scr || besthp<hp) {
722 				besthp=hp;
723 				scr=actor;
724 			}
725 		}
726 	}
727 	parameters->Clear();
728 	parameters->AddTarget(scr, 0, ga_flags);
729 	return parameters;
730 }
731 
Farthest(const Scriptable *,Targets * parameters,int ga_flags)732 Targets *GameScript::Farthest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
733 {
734 	const targettype *t = parameters->GetLastTarget(ST_ACTOR);
735 	parameters->Clear();
736 	if (t) {
737 		parameters->AddTarget(t->actor, 0, ga_flags);
738 	}
739 	return parameters;
740 }
741 
FarthestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)742 Targets *GameScript::FarthestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
743 {
744 	return XthNearestEnemyOf(parameters, -1, ga_flags);
745 }
746 
NearestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)747 Targets *GameScript::NearestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
748 {
749 	return XthNearestEnemyOf(parameters, 0, ga_flags);
750 }
751 
SecondNearestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)752 Targets *GameScript::SecondNearestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
753 {
754 	return XthNearestEnemyOf(parameters, 1, ga_flags);
755 }
756 
ThirdNearestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)757 Targets *GameScript::ThirdNearestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
758 {
759 	return XthNearestEnemyOf(parameters, 2, ga_flags);
760 }
761 
FourthNearestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)762 Targets *GameScript::FourthNearestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
763 {
764 	return XthNearestEnemyOf(parameters, 3, ga_flags);
765 }
766 
FifthNearestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)767 Targets *GameScript::FifthNearestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
768 {
769 	return XthNearestEnemyOf(parameters, 4, ga_flags);
770 }
771 
SixthNearestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)772 Targets *GameScript::SixthNearestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
773 {
774 	return XthNearestEnemyOf(parameters, 5, ga_flags);
775 }
776 
SeventhNearestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)777 Targets *GameScript::SeventhNearestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
778 {
779 	return XthNearestEnemyOf(parameters, 6, ga_flags);
780 }
781 
EighthNearestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)782 Targets *GameScript::EighthNearestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
783 {
784 	return XthNearestEnemyOf(parameters, 7, ga_flags);
785 }
786 
NinthNearestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)787 Targets *GameScript::NinthNearestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
788 {
789 	return XthNearestEnemyOf(parameters, 8, ga_flags);
790 }
791 
TenthNearestEnemyOf(const Scriptable *,Targets * parameters,int ga_flags)792 Targets *GameScript::TenthNearestEnemyOf(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
793 {
794 	return XthNearestEnemyOf(parameters, 9, ga_flags);
795 }
796 
NearestEnemySummoned(const Scriptable * Sender,Targets * parameters,int ga_flags)797 Targets *GameScript::NearestEnemySummoned(const Scriptable *Sender, Targets *parameters, int ga_flags)
798 {
799 	return ClosestEnemySummoned(Sender, parameters, ga_flags);
800 }
801 
NearestEnemyOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)802 Targets *GameScript::NearestEnemyOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
803 {
804 	return XthNearestEnemyOfType(Sender, parameters, 0, ga_flags);
805 }
806 
SecondNearestEnemyOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)807 Targets *GameScript::SecondNearestEnemyOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
808 {
809 	return XthNearestEnemyOfType(Sender, parameters, 1, ga_flags);
810 }
811 
ThirdNearestEnemyOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)812 Targets *GameScript::ThirdNearestEnemyOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
813 {
814 	return XthNearestEnemyOfType(Sender, parameters, 2, ga_flags);
815 }
816 
FourthNearestEnemyOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)817 Targets *GameScript::FourthNearestEnemyOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
818 {
819 	return XthNearestEnemyOfType(Sender, parameters, 3, ga_flags);
820 }
821 
FifthNearestEnemyOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)822 Targets *GameScript::FifthNearestEnemyOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
823 {
824 	return XthNearestEnemyOfType(Sender, parameters, 4, ga_flags);
825 }
826 
SixthNearestEnemyOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)827 Targets *GameScript::SixthNearestEnemyOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
828 {
829 	return XthNearestEnemyOfType(Sender, parameters, 5, ga_flags);
830 }
831 
SeventhNearestEnemyOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)832 Targets *GameScript::SeventhNearestEnemyOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
833 {
834 	return XthNearestEnemyOfType(Sender, parameters, 6, ga_flags);
835 }
836 
EighthNearestEnemyOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)837 Targets *GameScript::EighthNearestEnemyOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
838 {
839 	return XthNearestEnemyOfType(Sender, parameters, 7, ga_flags);
840 }
841 
NinthNearestEnemyOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)842 Targets *GameScript::NinthNearestEnemyOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
843 {
844 	return XthNearestEnemyOfType(Sender, parameters, 8, ga_flags);
845 }
846 
TenthNearestEnemyOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)847 Targets *GameScript::TenthNearestEnemyOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
848 {
849 	return XthNearestEnemyOfType(Sender, parameters, 9, ga_flags);
850 }
851 
NearestMyGroupOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)852 Targets *GameScript::NearestMyGroupOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
853 {
854 	return XthNearestMyGroupOfType(Sender, parameters, 0, ga_flags);
855 }
856 
SecondNearestMyGroupOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)857 Targets *GameScript::SecondNearestMyGroupOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
858 {
859 	return XthNearestMyGroupOfType(Sender, parameters, 1, ga_flags);
860 }
861 
ThirdNearestMyGroupOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)862 Targets *GameScript::ThirdNearestMyGroupOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
863 {
864 	return XthNearestMyGroupOfType(Sender, parameters, 2, ga_flags);
865 }
866 
FourthNearestMyGroupOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)867 Targets *GameScript::FourthNearestMyGroupOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
868 {
869 	return XthNearestMyGroupOfType(Sender, parameters, 3, ga_flags);
870 }
871 
FifthNearestMyGroupOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)872 Targets *GameScript::FifthNearestMyGroupOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
873 {
874 	return XthNearestMyGroupOfType(Sender, parameters, 4, ga_flags);
875 }
876 
SixthNearestMyGroupOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)877 Targets *GameScript::SixthNearestMyGroupOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
878 {
879 	return XthNearestMyGroupOfType(Sender, parameters, 5, ga_flags);
880 }
881 
SeventhNearestMyGroupOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)882 Targets *GameScript::SeventhNearestMyGroupOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
883 {
884 	return XthNearestMyGroupOfType(Sender, parameters, 6, ga_flags);
885 }
886 
EighthNearestMyGroupOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)887 Targets *GameScript::EighthNearestMyGroupOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
888 {
889 	return XthNearestMyGroupOfType(Sender, parameters, 7, ga_flags);
890 }
891 
NinthNearestMyGroupOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)892 Targets *GameScript::NinthNearestMyGroupOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
893 {
894 	return XthNearestMyGroupOfType(Sender, parameters, 8, ga_flags);
895 }
896 
TenthNearestMyGroupOfType(const Scriptable * Sender,Targets * parameters,int ga_flags)897 Targets *GameScript::TenthNearestMyGroupOfType(const Scriptable *Sender, Targets *parameters, int ga_flags)
898 {
899 	return XthNearestMyGroupOfType(Sender, parameters, 9, ga_flags);
900 }
901 
902 /* returns only living PC's? if not, alter getpartysize/getpc flag*/
NearestPC(const Scriptable * Sender,Targets * parameters,int ga_flags)903 Targets *GameScript::NearestPC(const Scriptable *Sender, Targets *parameters, int ga_flags)
904 {
905 	parameters->Clear();
906 	const Map *map = Sender->GetCurrentArea();
907 	const Game *game = core->GetGame();
908 	int i = game->GetPartySize(true);
909 	int mindist = -1;
910 	Actor *ac = NULL;
911 	while (i--) {
912 		Actor *newactor=game->GetPC(i,true);
913 		//NearestPC for PC's will not give themselves as a result
914 		//this might be different from the original engine
915 		if (Sender->Type == ST_ACTOR && (newactor == (const Actor *) Sender)) {
916 			continue;
917 		}
918 		if (newactor->GetCurrentArea()!=map) {
919 			continue;
920 		}
921 		int dist = Distance(Sender, newactor);
922 		if ( (mindist == -1) || (dist<mindist) ) {
923 			ac = newactor;
924 			mindist = dist;
925 		}
926 	}
927 	if (ac) {
928 		parameters->AddTarget(ac, 0, ga_flags);
929 	}
930 	return parameters;
931 }
932 
Nearest(const Scriptable *,Targets * parameters,int ga_flags)933 Targets *GameScript::Nearest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
934 {
935 	return XthNearestOf(parameters, 0, ga_flags);
936 }
937 
SecondNearest(const Scriptable *,Targets * parameters,int ga_flags)938 Targets *GameScript::SecondNearest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
939 {
940 	return XthNearestOf(parameters, 1, ga_flags);
941 }
942 
ThirdNearest(const Scriptable *,Targets * parameters,int ga_flags)943 Targets *GameScript::ThirdNearest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
944 {
945 	return XthNearestOf(parameters, 2, ga_flags);
946 }
947 
FourthNearest(const Scriptable *,Targets * parameters,int ga_flags)948 Targets *GameScript::FourthNearest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
949 {
950 	return XthNearestOf(parameters, 3, ga_flags);
951 }
952 
FifthNearest(const Scriptable *,Targets * parameters,int ga_flags)953 Targets *GameScript::FifthNearest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
954 {
955 	return XthNearestOf(parameters, 4, ga_flags);
956 }
957 
SixthNearest(const Scriptable *,Targets * parameters,int ga_flags)958 Targets *GameScript::SixthNearest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
959 {
960 	return XthNearestOf(parameters, 5, ga_flags);
961 }
962 
SeventhNearest(const Scriptable *,Targets * parameters,int ga_flags)963 Targets *GameScript::SeventhNearest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
964 {
965 	return XthNearestOf(parameters, 6, ga_flags);
966 }
967 
EighthNearest(const Scriptable *,Targets * parameters,int ga_flags)968 Targets *GameScript::EighthNearest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
969 {
970 	return XthNearestOf(parameters, 7, ga_flags);
971 }
972 
NinthNearest(const Scriptable *,Targets * parameters,int ga_flags)973 Targets *GameScript::NinthNearest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
974 {
975 	return XthNearestOf(parameters, 8, ga_flags);
976 }
977 
TenthNearest(const Scriptable *,Targets * parameters,int ga_flags)978 Targets *GameScript::TenthNearest(const Scriptable */*Sender*/, Targets *parameters, int ga_flags)
979 {
980 	return XthNearestOf(parameters, 9, ga_flags);
981 }
982 
SelectedCharacter(const Scriptable * Sender,Targets * parameters,int ga_flags)983 Targets *GameScript::SelectedCharacter(const Scriptable *Sender, Targets *parameters, int ga_flags)
984 {
985 	const Map *cm = Sender->GetCurrentArea();
986 	parameters->Clear();
987 	int i = cm->GetActorCount(true);
988 	while (i--) {
989 		Actor *ac=cm->GetActor(i,true);
990 		if (ac->GetCurrentArea()!=cm) {
991 			continue;
992 		}
993 		if (ac->IsSelected()) {
994 			parameters->AddTarget(ac, Distance(Sender, ac), ga_flags );
995 		}
996 	}
997 	return parameters;
998 }
999 
Nothing(const Scriptable *,Targets * parameters,int)1000 Targets *GameScript::Nothing(const Scriptable */*Sender*/, Targets* parameters, int /*ga_flags*/)
1001 {
1002 	parameters->Clear();
1003 	return parameters;
1004 }
1005 
1006 //-------------------------------------------------------------
1007 // IDS Functions
1008 //-------------------------------------------------------------
1009 
ID_Alignment(const Actor * actor,int parameter)1010 int GameScript::ID_Alignment(const Actor *actor, int parameter)
1011 {
1012 	int value = actor->GetStat( IE_ALIGNMENT );
1013 	int a = parameter&15;
1014 	if (a) {
1015 		if (a != ( value & 15 )) {
1016 			return 0;
1017 		}
1018 	}
1019 	a = parameter & 240;
1020 	if (a) {
1021 		if (a != ( value & 240 )) {
1022 			return 0;
1023 		}
1024 	}
1025 	return 1;
1026 }
1027 
ID_Allegiance(const Actor * actor,int parameter)1028 int GameScript::ID_Allegiance(const Actor *actor, int parameter)
1029 {
1030 	int value = actor->GetStat( IE_EA );
1031 	switch (parameter) {
1032 		case EA_GOODCUTOFF:
1033 			return value <= EA_GOODCUTOFF;
1034 
1035 		case EA_NOTGOOD:
1036 			return value >= EA_NOTGOOD;
1037 
1038 		case EA_NOTNEUTRAL:
1039 			return value >=EA_EVILCUTOFF || value <= EA_GOODCUTOFF;
1040 
1041 		case EA_NOTEVIL:
1042 			return value <= EA_NOTEVIL;
1043 
1044 		case EA_EVILCUTOFF:
1045 			return value >= EA_EVILCUTOFF;
1046 
1047 		case 0:
1048 		case EA_ANYTHING:
1049 			return true;
1050 
1051 	}
1052 	//default
1053 	return parameter == value;
1054 }
1055 
1056 // *_ALL constants are different in iwd2 due to different classes (see note below)
1057 // bard, cleric, druid, fighter, mage, paladin, ranger, thief
1058 static const int all_bg_classes[] = { 206, 204, 208, 203, 202, 207, 209, 205 };
1059 static const int all_iwd2_classes[] = { 202, 203, 204, 205, 209, 206, 207, 208 };
1060 
1061 // Dual-classed characters will detect only as their new class until their
1062 // original class is re-activated, when they will detect as a multi-class
1063 // GetClassLevel takes care of this automatically!
idclass(const Actor * actor,int parameter,bool iwd2)1064 inline bool idclass(const Actor *actor, int parameter, bool iwd2) {
1065 	int value = 0;
1066 	if (parameter < 202 || parameter > 209) {
1067 		value = actor->GetActiveClass();
1068 		return parameter==value;
1069 	}
1070 
1071 	const int *classes;
1072 	if (iwd2) {
1073 		classes = all_iwd2_classes;
1074 	} else {
1075 		classes = all_bg_classes;
1076 	}
1077 
1078 	// FIXME: unhardcode this ugly mess
1079 	// in IWD2, mage_all = sorcerer or wizard
1080 	// fighter_all = fighter, paladin or ranger (but not monk)
1081 	// cleric_all = druid or cleric
1082 	// thief_all = thief
1083 	// bard_all = bard
1084 	// paladin_all = paladin
1085 	// druid_all = druid
1086 	// ranger_all = ranger
1087 
1088 	// we got one of the *_ALL values
1089 	if (parameter == classes[4]) {
1090 		// MAGE_ALL (also sorcerers)
1091 		value = actor->GetMageLevel() + actor->GetSorcererLevel();
1092 	} else if (parameter == classes[3]) {
1093 		// FIGHTER_ALL (also monks)
1094 		if (iwd2) {
1095 			value = actor->GetFighterLevel() + actor->GetPaladinLevel() + actor->GetRangerLevel();
1096 		} else {
1097 			value = actor->GetFighterLevel() + actor->GetMonkLevel();
1098 		}
1099 	} else if (parameter == classes[1]) {
1100 		// CLERIC_ALL
1101 		if (iwd2) {
1102 			value = actor->GetClericLevel() + actor->GetDruidLevel();
1103 		} else {
1104 			value = actor->GetClericLevel();
1105 		}
1106 	} else if (parameter == classes[7]) {
1107 		// THIEF_ALL
1108 		value = actor->GetThiefLevel();
1109 	} else if (parameter == classes[0]) {
1110 		// BARD_ALL
1111 		value = actor->GetBardLevel();
1112 	} else if (parameter == classes[5]) {
1113 		// PALADIN_ALL
1114 		value = actor->GetPaladinLevel();
1115 	} else if (parameter == classes[2]) {
1116 		// DRUID_ALL
1117 		value = actor->GetDruidLevel();
1118 	} else if (parameter == classes[6]) {
1119 		// RANGER_ALL
1120 		value = actor->GetRangerLevel();
1121 	}
1122 	return value > 0;
1123 }
1124 
ID_Class(const Actor * actor,int parameter)1125 int GameScript::ID_Class(const Actor *actor, int parameter)
1126 {
1127 	if (core->HasFeature(GF_3ED_RULES)) {
1128 		//iwd2 has different values, see also the note for AVClass
1129 		return idclass(actor, parameter, 1);
1130 	}
1131 	return idclass(actor, parameter, 0);
1132 }
1133 
1134 // IE_CLASS holds only one class, not a bitmask like with iwd2 kits. The ids values
1135 // are friendly to binary comparison, so we just need to build such a class value
ID_ClassMask(const Actor * actor,int parameter)1136 int GameScript::ID_ClassMask(const Actor *actor, int parameter)
1137 {
1138 	// maybe we're lucky...
1139 	int value = actor->GetActiveClass();
1140 	if (parameter&(1<<(value-1))) return 1;
1141 
1142 	// otherwise iterate over all the classes
1143 	value = actor->GetClassMask();
1144 
1145 	if (parameter&value) return 1;
1146 	return 0;
1147 }
1148 
1149 // this is only present in iwd2
1150 // the function is identical to ID_Class, but uses the class20 IDS,
1151 // iwd2's class.ids is different than the rest, while class20 is identical (remnant)
ID_AVClass(const Actor * actor,int parameter)1152 int GameScript::ID_AVClass(const Actor *actor, int parameter)
1153 {
1154 	return idclass(actor, parameter, 0);
1155 }
1156 
ID_Race(const Actor * actor,int parameter)1157 int GameScript::ID_Race(const Actor *actor, int parameter)
1158 {
1159 	int value = actor->GetStat(IE_RACE);
1160 	return parameter==value;
1161 }
1162 
ID_Subrace(const Actor * actor,int parameter)1163 int GameScript::ID_Subrace(const Actor *actor, int parameter)
1164 {
1165 	int value = actor->GetStat(IE_SUBRACE);
1166 	return parameter==value;
1167 }
1168 
ID_Faction(const Actor * actor,int parameter)1169 int GameScript::ID_Faction(const Actor *actor, int parameter)
1170 {
1171 	int value = actor->GetStat(IE_FACTION);
1172 	return parameter==value;
1173 }
1174 
ID_Team(const Actor * actor,int parameter)1175 int GameScript::ID_Team(const Actor *actor, int parameter)
1176 {
1177 	int value = actor->GetStat(IE_TEAM);
1178 	return parameter==value;
1179 }
1180 
ID_Gender(const Actor * actor,int parameter)1181 int GameScript::ID_Gender(const Actor *actor, int parameter)
1182 {
1183 	int value = actor->GetStat(IE_SEX);
1184 	return parameter==value;
1185 }
1186 
ID_General(const Actor * actor,int parameter)1187 int GameScript::ID_General(const Actor *actor, int parameter)
1188 {
1189 	int value = actor->GetStat(IE_GENERAL);
1190 	return parameter==value;
1191 }
1192 
ID_Specific(const Actor * actor,int parameter)1193 int GameScript::ID_Specific(const Actor *actor, int parameter)
1194 {
1195 	int value = actor->GetStat(IE_SPECIFIC);
1196 	return parameter==value;
1197 }
1198 
1199 }
1200