1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003-2005 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 "voodooconst.h"
27
28 #include "AmbientMgr.h"
29 #include "Calendar.h"
30 #include "DialogHandler.h"
31 #include "Game.h"
32 #include "GameData.h"
33 #include "Polygon.h"
34 #include "TableMgr.h"
35 #include "Video.h"
36 #include "GUI/GameControl.h"
37 #include "math.h" //needs for acos
38 #include "Scriptable/Container.h"
39 #include "Scriptable/Door.h"
40 #include "Scriptable/InfoPoint.h"
41
42 namespace GemRB {
43
44 //-------------------------------------------------------------
45 // Trigger Functions
46 //-------------------------------------------------------------
47 // bg1 and bg2 have some dead bcs code - perhaps the first implementation
48 // of morale, since the uses suggest being able to detect panic
BreakingPoint(Scriptable * Sender,const Trigger *)49 int GameScript::BreakingPoint(Scriptable *Sender, const Trigger */*parameters*/)
50 {
51 int value=GetHappiness(Sender, core->GetGame()->Reputation );
52 return value < -300;
53 }
54
Reaction(Scriptable * Sender,const Trigger * parameters)55 int GameScript::Reaction(Scriptable *Sender, const Trigger *parameters)
56 {
57 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
58 if (!scr || scr->Type != ST_ACTOR) {
59 parameters->dump();
60 return 0;
61 }
62 int value = GetReaction((const Actor *) scr, Sender);
63 bool matched = value == parameters->int0Parameter;
64 if (matched) {
65 Sender->SetLastTrigger(trigger_reaction, scr->GetGlobalID());
66 }
67 return matched;
68 }
69
ReactionGT(Scriptable * Sender,const Trigger * parameters)70 int GameScript::ReactionGT(Scriptable *Sender, const Trigger *parameters)
71 {
72 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
73 if (!scr || scr->Type != ST_ACTOR) {
74 parameters->dump();
75 return 0;
76 }
77 int value = GetReaction((const Actor *) scr, Sender);
78 bool matched = value > parameters->int0Parameter;
79 if (matched) {
80 Sender->SetLastTrigger(trigger_reaction, scr->GetGlobalID());
81 }
82 return matched;
83 }
84
ReactionLT(Scriptable * Sender,const Trigger * parameters)85 int GameScript::ReactionLT(Scriptable *Sender, const Trigger *parameters)
86 {
87 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
88 if (!scr || scr->Type != ST_ACTOR) {
89 parameters->dump();
90 return 0;
91 }
92 int value = GetReaction((const Actor *) scr, Sender);
93 bool matched = value < parameters->int0Parameter;
94 if (matched) {
95 Sender->SetLastTrigger(trigger_reaction, scr->GetGlobalID());
96 }
97 return matched;
98 }
99
Happiness(Scriptable * Sender,const Trigger * parameters)100 int GameScript::Happiness(Scriptable *Sender, const Trigger *parameters)
101 {
102 int value=GetHappiness(Sender, core->GetGame()->Reputation );
103 return value == parameters->int0Parameter;
104 }
105
HappinessGT(Scriptable * Sender,const Trigger * parameters)106 int GameScript::HappinessGT(Scriptable *Sender, const Trigger *parameters)
107 {
108 int value=GetHappiness(Sender, core->GetGame()->Reputation );
109 return value > parameters->int0Parameter;
110 }
111
HappinessLT(Scriptable * Sender,const Trigger * parameters)112 int GameScript::HappinessLT(Scriptable *Sender, const Trigger *parameters)
113 {
114 int value=GetHappiness(Sender, core->GetGame()->Reputation );
115 return value < parameters->int0Parameter;
116 }
117
118 // these also take an object parameter, but reputation is global
119 // but we do need to use it to be precise for LastTrigger purposes
Reputation(Scriptable * Sender,const Trigger * parameters)120 int GameScript::Reputation(Scriptable *Sender, const Trigger *parameters)
121 {
122 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
123 bool matched = core->GetGame()->Reputation / 10 == (ieDword) parameters->int0Parameter;
124 if (matched && scr) {
125 Sender->SetLastTrigger(trigger_reputation, scr->GetGlobalID());
126 }
127 return matched;
128 }
129
ReputationGT(Scriptable * Sender,const Trigger * parameters)130 int GameScript::ReputationGT(Scriptable *Sender, const Trigger *parameters)
131 {
132 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
133 bool matched = core->GetGame()->Reputation / 10 > (ieDword) parameters->int0Parameter;
134 if (matched && scr) {
135 Sender->SetLastTrigger(trigger_reputation, scr->GetGlobalID());
136 }
137 return matched;
138 }
139
ReputationLT(Scriptable * Sender,const Trigger * parameters)140 int GameScript::ReputationLT(Scriptable *Sender, const Trigger *parameters)
141 {
142 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
143 bool matched = core->GetGame()->Reputation / 10 < (ieDword) parameters->int0Parameter;
144 if (matched && scr) {
145 Sender->SetLastTrigger(trigger_reputation, scr->GetGlobalID());
146 }
147 return matched;
148 }
149
Alignment(Scriptable * Sender,const Trigger * parameters)150 int GameScript::Alignment(Scriptable *Sender, const Trigger *parameters)
151 {
152 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
153 if (!scr || scr->Type != ST_ACTOR) {
154 return 0;
155 }
156 const Actor *actor = (const Actor *) scr;
157 bool matched = ID_Alignment(actor, parameters->int0Parameter);
158 if (matched) {
159 Sender->SetLastTrigger(trigger_alignment, actor->GetGlobalID());
160 }
161 return matched;
162 }
163
Allegiance(Scriptable * Sender,const Trigger * parameters)164 int GameScript::Allegiance(Scriptable *Sender, const Trigger *parameters)
165 {
166 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
167 if (!scr || scr->Type != ST_ACTOR) {
168 return 0;
169 }
170 const Actor *actor = (const Actor *) scr;
171 bool matched = ID_Allegiance(actor, parameters->int0Parameter);
172 if (matched) {
173 Sender->SetLastTrigger(trigger_allegiance, actor->GetGlobalID());
174 }
175 return matched;
176 }
177
178 //should return *_ALL stuff
Class(Scriptable * Sender,const Trigger * parameters)179 int GameScript::Class(Scriptable *Sender, const Trigger *parameters)
180 {
181 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
182 if (!scr || scr->Type != ST_ACTOR) {
183 return 0;
184 }
185 const Actor *actor = (const Actor *) scr;
186 bool matched = ID_Class(actor, parameters->int0Parameter);
187 if (matched) {
188 Sender->SetLastTrigger(trigger_class, actor->GetGlobalID());
189 }
190 return matched;
191 }
192
ClassEx(Scriptable * Sender,const Trigger * parameters)193 int GameScript::ClassEx(Scriptable *Sender, const Trigger *parameters)
194 {
195 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
196 if (!scr || scr->Type != ST_ACTOR) {
197 return 0;
198 }
199 const Actor *actor = (const Actor *) scr;
200 return ID_AVClass(actor, parameters->int0Parameter);
201 }
202
Faction(Scriptable * Sender,const Trigger * parameters)203 int GameScript::Faction(Scriptable *Sender, const Trigger *parameters)
204 {
205 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
206 if (!scr || scr->Type != ST_ACTOR) {
207 return 0;
208 }
209 const Actor *actor = (const Actor *) scr;
210 return ID_Faction(actor, parameters->int0Parameter);
211 }
212
Team(Scriptable * Sender,const Trigger * parameters)213 int GameScript::Team(Scriptable *Sender, const Trigger *parameters)
214 {
215 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
216 if (!scr || scr->Type != ST_ACTOR) {
217 return 0;
218 }
219 const Actor *actor = (const Actor *) scr;
220 return ID_Team(actor, parameters->int0Parameter);
221 }
222
SubRace(Scriptable * Sender,const Trigger * parameters)223 int GameScript::SubRace(Scriptable *Sender, const Trigger *parameters)
224 {
225 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
226 if (!scr || scr->Type != ST_ACTOR) {
227 return 0;
228 }
229 const Actor *actor = (const Actor *) scr;
230 //subrace trigger uses a weird system, cannot use ID_*
231 //return ID_Subrace( actor, parameters->int0Parameter);
232 int value = actor->GetStat(IE_SUBRACE);
233 if (value) {
234 value |= actor->GetStat(IE_RACE)<<16;
235 }
236 if (value == parameters->int0Parameter) {
237 return 1;
238 }
239 return 0;
240 }
241
242 //if object parameter is given (gemrb) it is used
243 //otherwise it works on the current object (iwd2)
IsTeamBitOn(Scriptable * Sender,const Trigger * parameters)244 int GameScript::IsTeamBitOn(Scriptable *Sender, const Trigger *parameters)
245 {
246 const Scriptable *scr = Sender;
247 if (parameters->objectParameter) {
248 scr = GetActorFromObject(Sender, parameters->objectParameter);
249 }
250 if (!scr || scr->Type != ST_ACTOR) {
251 return 0;
252 }
253 const Actor *actor = (const Actor *) scr;
254 if (actor->GetStat(IE_TEAM) & parameters->int0Parameter) {
255 return 1;
256 }
257 return 0;
258 }
259
NearbyDialog(Scriptable * Sender,const Trigger * parameters)260 int GameScript::NearbyDialog(Scriptable *Sender, const Trigger *parameters)
261 {
262 const Scriptable *target = Sender->GetCurrentArea()->GetActorByDialog(parameters->string0Parameter);
263 if ( !target ) {
264 return 0;
265 }
266 return CanSee( Sender, target, true, GA_NO_DEAD|GA_NO_HIDDEN|GA_NO_UNSCHEDULED );
267 }
268
269 //atm this checks for InParty and See, it is unsure what is required
IsValidForPartyDialog(Scriptable * Sender,const Trigger * parameters)270 int GameScript::IsValidForPartyDialog(Scriptable *Sender, const Trigger *parameters)
271 {
272 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
273 if (!scr) {
274 scr = Sender;
275 }
276 if (scr->Type != ST_ACTOR) {
277 return 0;
278 }
279 const Actor *target = (const Actor *) scr;
280 if (core->GetGame()->InParty(target) == -1) {
281 return 0;
282 }
283 //don't accept parties currently in dialog!
284 //this might disturb some modders, but this is the correct behaviour
285 //for example the aaquatah dialog in irenicus dungeon depends on it
286 const GameControl *gc = core->GetGameControl();
287 if (gc->dialoghandler->InDialog(scr)) {
288 return 0;
289 }
290
291 //don't accept parties with the no interrupt flag
292 //this fixes bug #2573808 on gamescript level
293 //(still someone has to turn the no interrupt flag off)
294 if(!target->GetDialog(GD_CHECK)) {
295 return 0;
296 }
297 return CanSee( Sender, target, false, GA_NO_DEAD|GA_NO_UNSCHEDULED );
298 }
299
InParty(Scriptable * Sender,const Trigger * parameters,bool allowdead)300 int GameScript::InParty(Scriptable *Sender, const Trigger *parameters, bool allowdead)
301 {
302 const Scriptable *scr;
303
304 if (parameters->objectParameter) {
305 scr = GetActorFromObject( Sender, parameters->objectParameter );
306 } else {
307 scr = Sender;
308 }
309
310 if (!scr || scr->Type != ST_ACTOR) {
311 return 0;
312 }
313
314 const Actor *act = (const Actor *) scr;
315 //don't allow dead, don't allow maze and similar effects
316 if (!allowdead && (!act->ValidTarget(GA_NO_DEAD) || act->GetStat(IE_AVATARREMOVAL) != 0)) {
317 return 0;
318 }
319
320 bool matched = core->GetGame()->InParty(act) >= 0;
321 if (matched) {
322 Sender->SetLastTrigger(trigger_inparty, scr->GetGlobalID());
323 }
324 return matched;
325 }
326
InParty(Scriptable * Sender,const Trigger * parameters)327 int GameScript::InParty(Scriptable *Sender, const Trigger *parameters)
328 {
329 return InParty(Sender, parameters, core->HasFeature(GF_IN_PARTY_ALLOWS_DEAD));
330 }
331
InPartyAllowDead(Scriptable * Sender,const Trigger * parameters)332 int GameScript::InPartyAllowDead(Scriptable *Sender, const Trigger *parameters)
333 {
334 return InParty(Sender, parameters, true);
335 }
336
InPartySlot(Scriptable * Sender,const Trigger * parameters)337 int GameScript::InPartySlot(Scriptable *Sender, const Trigger *parameters)
338 {
339 const Actor *actor = core->GetGame()->GetPC(parameters->int0Parameter, false);
340 return MatchActor(Sender, actor->GetGlobalID(), parameters->objectParameter);
341 }
342
Exists(Scriptable * Sender,const Trigger * parameters)343 int GameScript::Exists(Scriptable *Sender, const Trigger *parameters)
344 {
345 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
346 if (!scr) {
347 return 0;
348 }
349 Sender->SetLastTrigger(trigger_exists, scr->GetGlobalID());
350 return 1;
351 }
352
IsAClown(Scriptable * Sender,const Trigger * parameters)353 int GameScript::IsAClown(Scriptable *Sender, const Trigger *parameters)
354 {
355 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
356 if (!scr || scr->Type!=ST_ACTOR) {
357 return 0;
358 }
359 return 1;
360 }
361
IsGabber(Scriptable * Sender,const Trigger * parameters)362 int GameScript::IsGabber(Scriptable *Sender, const Trigger *parameters)
363 {
364 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
365 if (!scr || scr->Type!=ST_ACTOR) {
366 return 0;
367 }
368 if (core->GetGameControl()->dialoghandler->IsSpeaker(scr))
369 return 1;
370 return 0;
371 }
372
373 //returns true if the trap or infopoint is active
374 //returns true if the actor is active
375 //returns true if the sound source is active
376 //returns true if container is active
IsActive(Scriptable * Sender,const Trigger * parameters)377 int GameScript::IsActive(Scriptable *Sender, const Trigger *parameters)
378 {
379 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
380 if (!scr) {
381 const AmbientMgr *ambientmgr = core->GetAudioDrv()->GetAmbientMgr();
382 if (ambientmgr->isActive(parameters->objectParameter->objectName)) {
383 return 1;
384 }
385 return 0;
386 }
387
388 switch(scr->Type) {
389 case ST_ACTOR:
390 if (((const Actor *) scr)->Schedule(core->GetGame()->GameTime, true)) return 1;
391 return 0;
392 case ST_CONTAINER:
393 if (((const Container *) scr)->Flags & CONT_DISABLED) return 0;
394 return 1;
395
396 case ST_PROXIMITY: case ST_TRIGGER: case ST_TRAVEL:
397 if (((const InfoPoint *) scr)->Flags & (TRAP_DEACTIVATED | INFO_DOOR)) {
398 return 0;
399 }
400 return 1;
401 default:
402 return 0;
403 }
404 }
405
InTrap(Scriptable * Sender,const Trigger * parameters)406 int GameScript::InTrap(Scriptable *Sender, const Trigger *parameters)
407 {
408 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
409 if (!scr) {
410 return 0;
411 }
412 if (scr->GetInternalFlag()&IF_INTRAP) {
413 return 1;
414 }
415 return 0;
416 }
417
418 /* checks if targeted actor is in the specified region
419 GemRB allows different regions, referenced by int0Parameter
420 The polygons are stored in island<nn>.2da files */
OnIsland(Scriptable * Sender,const Trigger * parameters)421 int GameScript::OnIsland(Scriptable *Sender, const Trigger *parameters)
422 {
423 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
424 if (!scr) {
425 return 0;
426 }
427 const Gem_Polygon *p = GetPolygon2DA(parameters->int0Parameter);
428 if (!p) {
429 return 0;
430 }
431 return p->PointIn(scr->Pos);
432 }
433
School(Scriptable * Sender,const Trigger * parameters)434 int GameScript::School(Scriptable *Sender, const Trigger *parameters)
435 {
436 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
437 if (!scr || scr->Type!=ST_ACTOR) {
438 return 0;
439 }
440 const Actor *actor = (const Actor *) scr;
441 //only the low 2 bytes count
442 //the School values start from 1 to 9 and the first school value is 0x40
443 //so this mild hack will do
444 if (actor->GetStat(IE_KIT) == (ieDword) (0x20<<parameters->int0Parameter)) {
445 return 1;
446 }
447 return 0;
448 }
449
Kit(Scriptable * Sender,const Trigger * parameters)450 int GameScript::Kit(Scriptable *Sender, const Trigger *parameters)
451 {
452 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
453 if (!scr || scr->Type!=ST_ACTOR) {
454 return 0;
455 }
456 const Actor *actor = (const Actor *) scr;
457
458 ieDword kit = actor->GetStat(IE_KIT);
459 //TODO: fix baseclass / barbarian confusion
460
461 //IWD2 style kit matching (also used for mage schools)
462 if (kit == (ieDword) (parameters->int0Parameter)) {
463 return 1;
464 }
465 if (kit == (ieDword) (parameters->int0Parameter)) {
466 return 1;
467 }
468 return 0;
469 }
470
General(Scriptable * Sender,const Trigger * parameters)471 int GameScript::General(Scriptable *Sender, const Trigger *parameters)
472 {
473 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
474 if (!scr) {
475 scr = Sender;
476 }
477 if (scr->Type != ST_ACTOR) {
478 return 0;
479 }
480 const Actor *actor = (const Actor *) scr;
481 bool matched = ID_General(actor, parameters->int0Parameter);
482 if (matched) {
483 Sender->SetLastTrigger(trigger_general, actor->GetGlobalID());
484 }
485 return matched;
486 }
487
Specifics(Scriptable * Sender,const Trigger * parameters)488 int GameScript::Specifics(Scriptable *Sender, const Trigger *parameters)
489 {
490 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
491 if (!scr) {
492 scr = Sender;
493 }
494 if (scr->Type != ST_ACTOR) {
495 return 0;
496 }
497 const Actor *actor = (const Actor *) scr;
498 bool matched = ID_Specific(actor, parameters->int0Parameter);
499 if (matched) {
500 Sender->SetLastTrigger(trigger_specifics, actor->GetGlobalID());
501 }
502 return matched;
503 }
504
BitCheck(Scriptable * Sender,const Trigger * parameters)505 int GameScript::BitCheck(Scriptable *Sender, const Trigger *parameters)
506 {
507 bool valid=true;
508
509 ieDword value = CheckVariable(Sender, parameters->string0Parameter, &valid );
510 if (valid && value & parameters->int0Parameter) return 1;
511 return 0;
512 }
513
BitCheckExact(Scriptable * Sender,const Trigger * parameters)514 int GameScript::BitCheckExact(Scriptable *Sender, const Trigger *parameters)
515 {
516 bool valid=true;
517
518 ieDword value = CheckVariable(Sender, parameters->string0Parameter, &valid );
519 if (valid) {
520 ieDword tmp = (ieDword) parameters->int0Parameter ;
521 if ((value & tmp) == tmp) return 1;
522 }
523 return 0;
524 }
525
526 //OP_OR would make sense only if this trigger changes the value of the variable
527 //should I do that???
BitGlobal_Trigger(Scriptable * Sender,const Trigger * parameters)528 int GameScript::BitGlobal_Trigger(Scriptable *Sender, const Trigger *parameters)
529 {
530 bool valid=true;
531
532 ieDword value = CheckVariable(Sender, parameters->string0Parameter, &valid );
533 if (valid) {
534 HandleBitMod(value, parameters->int0Parameter, parameters->int1Parameter);
535 if (value!=0) return 1;
536 }
537 return 0;
538 }
539
GlobalOrGlobal_Trigger(Scriptable * Sender,const Trigger * parameters)540 int GameScript::GlobalOrGlobal_Trigger(Scriptable *Sender, const Trigger *parameters)
541 {
542 bool valid=true;
543
544 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, &valid);
545 if (valid) {
546 if (value1) return 1;
547 ieDword value2 = CheckVariable(Sender, parameters->string1Parameter, &valid);
548 if (valid && value2) return 1;
549 }
550 return 0;
551 }
552
GlobalAndGlobal_Trigger(Scriptable * Sender,const Trigger * parameters)553 int GameScript::GlobalAndGlobal_Trigger(Scriptable *Sender, const Trigger *parameters)
554 {
555 bool valid=true;
556
557 ieDword value1 = CheckVariable( Sender, parameters->string0Parameter, &valid );
558 if (valid && value1) {
559 ieDword value2 = CheckVariable( Sender, parameters->string1Parameter, &valid );
560 if (valid && value2) return 1;
561 }
562 return 0;
563 }
564
GlobalBAndGlobal_Trigger(Scriptable * Sender,const Trigger * parameters)565 int GameScript::GlobalBAndGlobal_Trigger(Scriptable *Sender, const Trigger *parameters)
566 {
567 bool valid=true;
568
569 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, &valid );
570 if (valid) {
571 ieDword value2 = CheckVariable(Sender, parameters->string1Parameter, &valid );
572 if (valid && (value1 & value2) != 0) return 1;
573 }
574 return 0;
575 }
576
GlobalBAndGlobalExact(Scriptable * Sender,const Trigger * parameters)577 int GameScript::GlobalBAndGlobalExact(Scriptable *Sender, const Trigger *parameters)
578 {
579 bool valid=true;
580
581 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, &valid );
582 if (valid) {
583 ieDword value2 = CheckVariable(Sender, parameters->string1Parameter, &valid );
584 if (valid && (value1 & value2) == value2) return 1;
585 }
586 return 0;
587 }
588
GlobalBitGlobal_Trigger(Scriptable * Sender,const Trigger * parameters)589 int GameScript::GlobalBitGlobal_Trigger(Scriptable *Sender, const Trigger *parameters)
590 {
591 bool valid=true;
592
593 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, &valid );
594 if (valid) {
595 ieDword value2 = CheckVariable(Sender, parameters->string1Parameter, &valid );
596 if (valid) {
597 HandleBitMod( value1, value2, parameters->int1Parameter);
598 if (value1!=0) return 1;
599 }
600 }
601 return 0;
602 }
603
604 //no what exactly this trigger would do, defined in iwd2, but never used
605 //i just assume it sets a global in the trigger block
TriggerSetGlobal(Scriptable * Sender,const Trigger * parameters)606 int GameScript::TriggerSetGlobal(Scriptable *Sender, const Trigger *parameters)
607 {
608 SetVariable( Sender, parameters->string0Parameter, parameters->int0Parameter );
609 return 1;
610 }
611
612 //would this function also alter the variable?
Xor(Scriptable * Sender,const Trigger * parameters)613 int GameScript::Xor(Scriptable *Sender, const Trigger *parameters)
614 {
615 bool valid=true;
616
617 ieDword value = CheckVariable(Sender, parameters->string0Parameter, &valid );
618 if (valid && (value ^ parameters->int0Parameter) != 0) return 1;
619 return 0;
620 }
621
622 //TODO:
623 //no sprite is dead for iwd, they use KILL_<name>_CNT
NumDead(Scriptable * Sender,const Trigger * parameters)624 int GameScript::NumDead(Scriptable *Sender, const Trigger *parameters)
625 {
626 ieDword value;
627
628 if (core->HasFeature(GF_HAS_KAPUTZ) ) {
629 value = CheckVariable(Sender, parameters->string0Parameter, "KAPUTZ");
630 } else {
631 ieVariable VariableName;
632 snprintf(VariableName, 32, core->GetDeathVarFormat(), parameters->string0Parameter);
633 value = CheckVariable(Sender, VariableName, "GLOBAL" );
634 }
635 return ( value == (ieDword) parameters->int0Parameter );
636 }
637
NumDeadGT(Scriptable * Sender,const Trigger * parameters)638 int GameScript::NumDeadGT(Scriptable *Sender, const Trigger *parameters)
639 {
640 ieDword value;
641
642 if (core->HasFeature(GF_HAS_KAPUTZ) ) {
643 value = CheckVariable(Sender, parameters->string0Parameter, "KAPUTZ");
644 } else {
645 ieVariable VariableName;
646 snprintf(VariableName, 32, core->GetDeathVarFormat(), parameters->string0Parameter);
647 value = CheckVariable(Sender, VariableName, "GLOBAL" );
648 }
649 return ( value > (ieDword) parameters->int0Parameter );
650 }
651
NumDeadLT(Scriptable * Sender,const Trigger * parameters)652 int GameScript::NumDeadLT(Scriptable *Sender, const Trigger *parameters)
653 {
654 ieDword value;
655
656 if (core->HasFeature(GF_HAS_KAPUTZ) ) {
657 value = CheckVariable(Sender, parameters->string0Parameter, "KAPUTZ");
658 } else {
659 ieVariable VariableName;
660
661 snprintf(VariableName, 32, core->GetDeathVarFormat(), parameters->string0Parameter);
662 value = CheckVariable(Sender, VariableName, "GLOBAL" );
663 }
664 return ( value < (ieDword) parameters->int0Parameter );
665 }
666
G_Trigger(Scriptable * Sender,const Trigger * parameters)667 int GameScript::G_Trigger(Scriptable *Sender, const Trigger *parameters)
668 {
669 ieDwordSigned value = CheckVariable(Sender, parameters->string0Parameter, "GLOBAL" );
670 return ( value == parameters->int0Parameter );
671 }
672
Global(Scriptable * Sender,const Trigger * parameters)673 int GameScript::Global(Scriptable *Sender, const Trigger *parameters)
674 {
675 bool valid=true;
676
677 ieDwordSigned value = CheckVariable(Sender, parameters->string0Parameter, &valid );
678 if (valid) {
679 if ( value == parameters->int0Parameter ) return 1;
680 }
681 return 0;
682 }
683
GLT_Trigger(Scriptable * Sender,const Trigger * parameters)684 int GameScript::GLT_Trigger(Scriptable *Sender, const Trigger *parameters)
685 {
686 ieDwordSigned value = CheckVariable(Sender, parameters->string0Parameter,"GLOBAL" );
687 return ( value < parameters->int0Parameter );
688 }
689
GlobalLT(Scriptable * Sender,const Trigger * parameters)690 int GameScript::GlobalLT(Scriptable *Sender, const Trigger *parameters)
691 {
692 bool valid=true;
693
694 ieDwordSigned value = CheckVariable(Sender, parameters->string0Parameter, &valid );
695 if (valid && value < parameters->int0Parameter) return 1;
696 return 0;
697 }
698
GGT_Trigger(Scriptable * Sender,const Trigger * parameters)699 int GameScript::GGT_Trigger(Scriptable *Sender, const Trigger *parameters)
700 {
701 ieDwordSigned value = CheckVariable(Sender, parameters->string0Parameter, "GLOBAL" );
702 return ( value > parameters->int0Parameter );
703 }
704
GlobalGT(Scriptable * Sender,const Trigger * parameters)705 int GameScript::GlobalGT(Scriptable *Sender, const Trigger *parameters)
706 {
707 bool valid=true;
708
709 ieDwordSigned value = CheckVariable(Sender, parameters->string0Parameter, &valid );
710 if (valid && value > parameters->int0Parameter) return 1;
711 return 0;
712 }
713
GlobalLTGlobal(Scriptable * Sender,const Trigger * parameters)714 int GameScript::GlobalLTGlobal(Scriptable *Sender, const Trigger *parameters)
715 {
716 bool valid=true;
717
718 ieDwordSigned value1 = CheckVariable(Sender, parameters->string0Parameter, &valid );
719 if (valid) {
720 ieDwordSigned value2 = CheckVariable(Sender, parameters->string1Parameter, &valid );
721 if (valid && value1 < value2) return 1;
722 }
723 return 0;
724 }
725
GlobalGTGlobal(Scriptable * Sender,const Trigger * parameters)726 int GameScript::GlobalGTGlobal(Scriptable *Sender, const Trigger *parameters)
727 {
728 bool valid=true;
729
730 ieDwordSigned value1 = CheckVariable(Sender, parameters->string0Parameter, &valid );
731 if (valid) {
732 ieDwordSigned value2 = CheckVariable(Sender, parameters->string1Parameter, &valid );
733 if (valid && value1 > value2) return 1;
734 }
735 return 0;
736 }
737
GlobalsEqual(Scriptable * Sender,const Trigger * parameters)738 int GameScript::GlobalsEqual(Scriptable *Sender, const Trigger *parameters)
739 {
740 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, "GLOBAL" );
741 ieDword value2 = CheckVariable(Sender, parameters->string1Parameter, "GLOBAL" );
742 return ( value1 == value2 );
743 }
744
GlobalsGT(Scriptable * Sender,const Trigger * parameters)745 int GameScript::GlobalsGT(Scriptable *Sender, const Trigger *parameters)
746 {
747 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, "GLOBAL" );
748 ieDword value2 = CheckVariable(Sender, parameters->string1Parameter, "GLOBAL" );
749 return ( value1 > value2 );
750 }
751
GlobalsLT(Scriptable * Sender,const Trigger * parameters)752 int GameScript::GlobalsLT(Scriptable *Sender, const Trigger *parameters)
753 {
754 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, "GLOBAL" );
755 ieDword value2 = CheckVariable(Sender, parameters->string1Parameter, "GLOBAL" );
756 return ( value1 < value2 );
757 }
758
LocalsEqual(Scriptable * Sender,const Trigger * parameters)759 int GameScript::LocalsEqual(Scriptable *Sender, const Trigger *parameters)
760 {
761 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, "LOCALS" );
762 ieDword value2 = CheckVariable(Sender, parameters->string1Parameter, "LOCALS" );
763 return ( value1 == value2 );
764 }
765
LocalsGT(Scriptable * Sender,const Trigger * parameters)766 int GameScript::LocalsGT(Scriptable *Sender, const Trigger *parameters)
767 {
768 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, "LOCALS" );
769 ieDword value2 = CheckVariable(Sender, parameters->string1Parameter, "LOCALS" );
770 return ( value1 > value2 );
771 }
772
LocalsLT(Scriptable * Sender,const Trigger * parameters)773 int GameScript::LocalsLT(Scriptable *Sender, const Trigger *parameters)
774 {
775 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, "LOCALS" );
776 ieDword value2 = CheckVariable(Sender, parameters->string1Parameter, "LOCALS" );
777 return ( value1 < value2 );
778 }
779
RealGlobalTimerExact(Scriptable * Sender,const Trigger * parameters)780 int GameScript::RealGlobalTimerExact(Scriptable *Sender, const Trigger *parameters)
781 {
782 bool valid=true;
783
784 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, parameters->string1Parameter, &valid );
785 if (valid && value1) {
786 ieDword value2 = core->GetGame()->RealTime;
787 if ( value1 == value2 ) return 1;
788 }
789 return 0;
790 }
791
RealGlobalTimerExpired(Scriptable * Sender,const Trigger * parameters)792 int GameScript::RealGlobalTimerExpired(Scriptable *Sender, const Trigger *parameters)
793 {
794 bool valid=true;
795
796 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, parameters->string1Parameter, &valid );
797 if (valid && value1 && value1 < core->GetGame()->RealTime) return 1;
798 return 0;
799 }
800
RealGlobalTimerNotExpired(Scriptable * Sender,const Trigger * parameters)801 int GameScript::RealGlobalTimerNotExpired(Scriptable *Sender, const Trigger *parameters)
802 {
803 bool valid=true;
804
805 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, parameters->string1Parameter, &valid );
806 if (valid && value1 && value1 > core->GetGame()->RealTime) return 1;
807 return 0;
808 }
809
GlobalTimerExact(Scriptable * Sender,const Trigger * parameters)810 int GameScript::GlobalTimerExact(Scriptable *Sender, const Trigger *parameters)
811 {
812 bool valid=true;
813
814 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, parameters->string1Parameter, &valid );
815 if (valid && value1 == core->GetGame()->GameTime) return 1;
816 return 0;
817 }
818
GlobalTimerExpired(Scriptable * Sender,const Trigger * parameters)819 int GameScript::GlobalTimerExpired(Scriptable *Sender, const Trigger *parameters)
820 {
821 bool valid=true;
822
823 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, parameters->string1Parameter, &valid );
824 if (valid && (core->HasFeature(GF_ZERO_TIMER_IS_VALID) || value1)) {
825 if ( value1 < core->GetGame()->GameTime ) return 1;
826 }
827 return 0;
828 }
829
830 //globaltimernotexpired returns false if the timer doesn't exist or is zero
GlobalTimerNotExpired(Scriptable * Sender,const Trigger * parameters)831 int GameScript::GlobalTimerNotExpired(Scriptable *Sender, const Trigger *parameters)
832 {
833 bool valid=true;
834
835 ieDword value1 = CheckVariable(Sender, parameters->string0Parameter, parameters->string1Parameter, &valid );
836 if (valid && value1 && value1 > core->GetGame()->GameTime) return 1;
837 return 0;
838 }
839
840 //globaltimerstarted returns false if the timer doesn't exist
GlobalTimerStarted(Scriptable * Sender,const Trigger * parameters)841 int GameScript::GlobalTimerStarted(Scriptable *Sender, const Trigger *parameters)
842 {
843 bool valid = VariableExists(Sender, parameters->string0Parameter, parameters->string1Parameter);
844 if (valid) {
845 return 1;
846 }
847 return 0;
848 }
849
WasInDialog(Scriptable * Sender,const Trigger *)850 int GameScript::WasInDialog(Scriptable *Sender, const Trigger */*parameters*/)
851 {
852 return Sender->MatchTrigger(trigger_wasindialog);
853 }
854
OnCreation(Scriptable * Sender,const Trigger *)855 int GameScript::OnCreation(Scriptable *Sender, const Trigger */*parameters*/)
856 {
857 return Sender->MatchTrigger(trigger_oncreation);
858 }
859
SummoningLimit(Scriptable * Sender,const Trigger * parameters)860 int GameScript::SummoningLimit(Scriptable *Sender, const Trigger *parameters)
861 {
862 const Map *map = Sender->GetCurrentArea();
863 if (!map) return 0;
864
865 int sl = map->CountSummons(GA_NO_DEAD, SEX_SUMMON);
866 if (sl == parameters->int0Parameter) return 1;
867 return 0;
868 }
869
SummoningLimitGT(Scriptable * Sender,const Trigger * parameters)870 int GameScript::SummoningLimitGT(Scriptable *Sender, const Trigger *parameters)
871 {
872 const Map *map = Sender->GetCurrentArea();
873 if (!map) return 0;
874
875 int sl = map->CountSummons(GA_NO_DEAD, SEX_SUMMON);
876 if (sl > parameters->int0Parameter) return 1;
877 return 0;
878 }
879
SummoningLimitLT(Scriptable * Sender,const Trigger * parameters)880 int GameScript::SummoningLimitLT(Scriptable *Sender, const Trigger *parameters)
881 {
882 const Map *map = Sender->GetCurrentArea();
883 if (!map) return 0;
884
885 int sl = map->CountSummons(GA_NO_DEAD, SEX_SUMMON);
886 if (sl < parameters->int0Parameter) return 1;
887 return 0;
888 }
889
890
NumItemsParty(Scriptable *,const Trigger * parameters)891 int GameScript::NumItemsParty(Scriptable */*Sender*/, const Trigger *parameters)
892 {
893 int cnt = 0;
894 const Game *game = core->GetGame();
895
896 int i = game->GetPartySize(true);
897 while(i--) {
898 const Actor *actor = game->GetPC(i, true);
899 cnt += actor->inventory.CountItems(parameters->string0Parameter, true);
900 }
901 return cnt==parameters->int0Parameter;
902 }
903
NumItemsPartyGT(Scriptable *,const Trigger * parameters)904 int GameScript::NumItemsPartyGT(Scriptable */*Sender*/, const Trigger *parameters)
905 {
906 int cnt = 0;
907 const Game *game = core->GetGame();
908
909 int i = game->GetPartySize(true);
910 while(i--) {
911 const Actor *actor = game->GetPC(i, true);
912 cnt += actor->inventory.CountItems(parameters->string0Parameter, true);
913 }
914 return cnt>parameters->int0Parameter;
915 }
916
NumItemsPartyLT(Scriptable *,const Trigger * parameters)917 int GameScript::NumItemsPartyLT(Scriptable */*Sender*/, const Trigger *parameters)
918 {
919 int cnt = 0;
920 const Game *game = core->GetGame();
921
922 int i = game->GetPartySize(true);
923 while(i--) {
924 const Actor *actor = game->GetPC(i, true);
925 cnt += actor->inventory.CountItems(parameters->string0Parameter, true);
926 }
927 return cnt<parameters->int0Parameter;
928 }
929
NumItems(Scriptable * Sender,const Trigger * parameters)930 int GameScript::NumItems(Scriptable *Sender, const Trigger *parameters)
931 {
932 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
933 if (!tar) {
934 return 0;
935 }
936
937 const Inventory *inv = nullptr;
938 switch (tar->Type) {
939 case ST_ACTOR:
940 inv = &(((const Actor *) tar)->inventory);
941 break;
942 case ST_CONTAINER:
943 inv = &(((const Container *) tar)->inventory);
944 break;
945 default:;
946 }
947 if (!inv) {
948 return 0;
949 }
950
951 int cnt = inv->CountItems(parameters->string0Parameter, true);
952 return cnt==parameters->int0Parameter;
953 }
954
TotalItemCnt(Scriptable * Sender,const Trigger * parameters)955 int GameScript::TotalItemCnt(Scriptable *Sender, const Trigger *parameters)
956 {
957 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
958 if ( !tar || tar->Type!=ST_ACTOR) {
959 return 0;
960 }
961 const Actor *actor = (const Actor *) tar;
962 int cnt = actor->inventory.CountItems("", true); //shall we count heaps or not?
963 return cnt==parameters->int0Parameter;
964 }
965
TotalItemCntExclude(Scriptable * Sender,const Trigger * parameters)966 int GameScript::TotalItemCntExclude(Scriptable *Sender, const Trigger *parameters)
967 {
968 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
969 if ( !tar || tar->Type!=ST_ACTOR) {
970 return 0;
971 }
972 const Actor *actor = (const Actor *) tar;
973 int cnt = actor->inventory.CountItems("", true) - actor->inventory.CountItems(parameters->string0Parameter, true); //shall we count heaps or not?
974 return cnt==parameters->int0Parameter;
975 }
976
NumItemsGT(Scriptable * Sender,const Trigger * parameters)977 int GameScript::NumItemsGT(Scriptable *Sender, const Trigger *parameters)
978 {
979 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
980 if (!tar) {
981 return 0;
982 }
983
984 const Inventory *inv = NULL;
985 switch (tar->Type) {
986 case ST_ACTOR:
987 inv = &(((const Actor *) tar)->inventory);
988 break;
989 case ST_CONTAINER:
990 inv = &(((const Container *) tar)->inventory);
991 break;
992 default:;
993 }
994 if (!inv) {
995 return 0;
996 }
997
998 int cnt = inv->CountItems(parameters->string0Parameter, true);
999 return cnt>parameters->int0Parameter;
1000 }
1001
TotalItemCntGT(Scriptable * Sender,const Trigger * parameters)1002 int GameScript::TotalItemCntGT(Scriptable *Sender, const Trigger *parameters)
1003 {
1004 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
1005 if (!tar || tar->Type!=ST_ACTOR) {
1006 return 0;
1007 }
1008 const Actor *actor = (const Actor *) tar;
1009 int cnt = actor->inventory.CountItems("", true); //shall we count heaps or not?
1010 return cnt>parameters->int0Parameter;
1011 }
1012
TotalItemCntExcludeGT(Scriptable * Sender,const Trigger * parameters)1013 int GameScript::TotalItemCntExcludeGT(Scriptable *Sender, const Trigger *parameters)
1014 {
1015 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
1016 if (!tar || tar->Type!=ST_ACTOR) {
1017 return 0;
1018 }
1019 const Actor *actor = (const Actor *) tar;
1020 int cnt = actor->inventory.CountItems("", true) - actor->inventory.CountItems(parameters->string0Parameter, true); //shall we count heaps or not?
1021 return cnt>parameters->int0Parameter;
1022 }
1023
NumItemsLT(Scriptable * Sender,const Trigger * parameters)1024 int GameScript::NumItemsLT(Scriptable *Sender, const Trigger *parameters)
1025 {
1026 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
1027 if (!tar) {
1028 return 0;
1029 }
1030
1031 const Inventory *inv = nullptr;
1032 switch (tar->Type) {
1033 case ST_ACTOR:
1034 inv = &(((const Actor *) tar)->inventory);
1035 break;
1036 case ST_CONTAINER:
1037 inv = &(((const Container *) tar)->inventory);
1038 break;
1039 default:;
1040 }
1041 if (!inv) {
1042 return 0;
1043 }
1044
1045 int cnt = inv->CountItems(parameters->string0Parameter, true);
1046 return cnt<parameters->int0Parameter;
1047 }
1048
TotalItemCntLT(Scriptable * Sender,const Trigger * parameters)1049 int GameScript::TotalItemCntLT(Scriptable *Sender, const Trigger *parameters)
1050 {
1051 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
1052 if ( !tar || tar->Type!=ST_ACTOR) {
1053 return 0;
1054 }
1055 const Actor *actor = (const Actor *) tar;
1056 int cnt = actor->inventory.CountItems("", true); //shall we count heaps or not?
1057 return cnt<parameters->int0Parameter;
1058 }
1059
TotalItemCntExcludeLT(Scriptable * Sender,const Trigger * parameters)1060 int GameScript::TotalItemCntExcludeLT(Scriptable *Sender, const Trigger *parameters)
1061 {
1062 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
1063 if ( !tar || tar->Type!=ST_ACTOR) {
1064 return 0;
1065 }
1066 const Actor *actor = (const Actor *) tar;
1067 int cnt = actor->inventory.CountItems("", true) - actor->inventory.CountItems(parameters->string0Parameter, true); //shall we count heaps or not?
1068 return cnt<parameters->int0Parameter;
1069 }
1070
1071 //the int0 parameter is an addition, normally it is 0
Contains(Scriptable * Sender,const Trigger * parameters)1072 int GameScript::Contains(Scriptable *Sender, const Trigger *parameters)
1073 {
1074 //actually this should be a container
1075 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
1076 if ( !tar || tar->Type!=ST_CONTAINER) {
1077 return 0;
1078 }
1079 const Container *cnt = (const Container *) tar;
1080 if (HasItemCore(&cnt->inventory, parameters->string0Parameter, parameters->int0Parameter)) {
1081 return 1;
1082 }
1083 return 0;
1084 }
1085
StoreHasItem(Scriptable *,const Trigger * parameters)1086 int GameScript::StoreHasItem(Scriptable */*Sender*/, const Trigger *parameters)
1087 {
1088 return StoreHasItemCore(parameters->string0Parameter, parameters->string1Parameter);
1089 }
1090
1091 //the int0 parameter is an addition, normally it is 0
HasItem(Scriptable * Sender,const Trigger * parameters)1092 int GameScript::HasItem(Scriptable *Sender, const Trigger *parameters)
1093 {
1094 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1095 if ( !scr ) {
1096 return 0;
1097 }
1098 const Inventory *inventory = nullptr;
1099 switch (scr->Type) {
1100 case ST_ACTOR:
1101 inventory = &((const Actor *) scr)->inventory;
1102 break;
1103 case ST_CONTAINER:
1104 inventory = &((const Container *) scr)->inventory;
1105 break;
1106 default:
1107 break;
1108 }
1109 if (inventory && HasItemCore(inventory, parameters->string0Parameter, parameters->int0Parameter) ) {
1110 return 1;
1111 }
1112 return 0;
1113 }
1114
ItemIsIdentified(Scriptable * Sender,const Trigger * parameters)1115 int GameScript::ItemIsIdentified(Scriptable *Sender, const Trigger *parameters)
1116 {
1117 // hardcode the Nothing filtering exception (needed for most iwd2 dialog uses)
1118 bool nothing = parameters->objectParameter[0].objectFilters[0] == 255;
1119 if (nothing) {
1120 // reset the filter to 19 LastTalkedToBy
1121 parameters->objectParameter[0].objectFilters[0] = 19;
1122 }
1123 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1124 if ( !scr || scr->Type!=ST_ACTOR) {
1125 return 0;
1126 }
1127 const Actor *actor = (const Actor *) scr;
1128 if (HasItemCore(&actor->inventory, parameters->string0Parameter, IE_INV_ITEM_IDENTIFIED) ) {
1129 return 1;
1130 }
1131 return 0;
1132 }
1133
1134 /** if the string is zero, then it will return true if there is any item in the slot (BG2)*/
1135 /** if the string is non-zero, it will return true, if the given item was in the slot (IWD2)*/
HasItemSlot(Scriptable * Sender,const Trigger * parameters)1136 int GameScript::HasItemSlot(Scriptable *Sender, const Trigger *parameters)
1137 {
1138 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1139 if ( !scr || scr->Type!=ST_ACTOR) {
1140 return 0;
1141 }
1142 const Actor *actor = (const Actor *) scr;
1143 //this might require a conversion of the slots
1144 if (actor->inventory.HasItemInSlot(parameters->string0Parameter, parameters->int0Parameter) ) {
1145 return 1;
1146 }
1147 return 0;
1148 }
1149
1150 //this is a GemRB extension
1151 //HasItemTypeSlot(Object, SLOT, ItemType)
1152 //returns true if the item in SLOT is of ItemType
HasItemTypeSlot(Scriptable * Sender,const Trigger * parameters)1153 int GameScript::HasItemTypeSlot(Scriptable *Sender, const Trigger *parameters)
1154 {
1155 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1156 if ( !scr || scr->Type!=ST_ACTOR) {
1157 return 0;
1158 }
1159 const Inventory *inv = &((const Actor *) scr)->inventory;
1160 if (parameters->int0Parameter>=inv->GetSlotCount()) {
1161 return 0;
1162 }
1163 const CREItem *slot = inv->GetSlotItem(parameters->int0Parameter);
1164 if (!slot) {
1165 return 0;
1166 }
1167 const Item *itm = gamedata->GetItem(slot->ItemResRef);
1168 if (!itm) {
1169 return 0;
1170 }
1171 int itemtype = itm->ItemType;
1172 gamedata->FreeItem(itm, slot->ItemResRef);
1173 if (itemtype==parameters->int1Parameter) {
1174 return 1;
1175 }
1176 return 0;
1177 }
1178
HasItemEquipped(Scriptable * Sender,const Trigger * parameters)1179 int GameScript::HasItemEquipped(Scriptable * Sender, const Trigger *parameters)
1180 {
1181 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1182 if ( !scr || scr->Type!=ST_ACTOR) {
1183 return 0;
1184 }
1185 const Actor *actor = (const Actor *) scr;
1186 // HACK: temporarily look at all items, since we now set the bit only for weapons
1187 // bg2/ddguard7.baf is the only user with something else - the strohm mask helmet
1188 if (actor->inventory.HasItem(parameters->string0Parameter, IE_INV_ITEM_EQUIPPED*0) ) {
1189 return 1;
1190 }
1191 return 0;
1192 }
1193
Acquired(Scriptable * Sender,const Trigger * parameters)1194 int GameScript::Acquired(Scriptable * Sender, const Trigger *parameters)
1195 {
1196 if ( Sender->Type!=ST_ACTOR) {
1197 return 0;
1198 }
1199 const Actor *actor = (const Actor *) Sender;
1200 if (actor->inventory.HasItem(parameters->string0Parameter, IE_INV_ITEM_ACQUIRED) ) {
1201 return 1;
1202 }
1203 return 0;
1204 }
1205
1206 /** this trigger accepts a numeric parameter, this number is the same as inventory flags
1207 like: 1 - identified, 2 - unstealable, 4 - stolen, 8 - undroppable, etc. */
1208 /** this is a GemRB extension */
PartyHasItem(Scriptable *,const Trigger * parameters)1209 int GameScript::PartyHasItem(Scriptable * /*Sender*/, const Trigger *parameters)
1210 {
1211 const Game *game = core->GetGame();
1212
1213 int i = game->GetPartySize(true);
1214 while(i--) {
1215 const Actor *actor = game->GetPC(i, true);
1216 if (HasItemCore(&actor->inventory, parameters->string0Parameter, parameters->int0Parameter) ) {
1217 return 1;
1218 }
1219 }
1220 return 0;
1221 }
1222
PartyHasItemIdentified(Scriptable *,const Trigger * parameters)1223 int GameScript::PartyHasItemIdentified(Scriptable * /*Sender*/, const Trigger *parameters)
1224 {
1225 const Game *game = core->GetGame();
1226
1227 int i = game->GetPartySize(true);
1228 while(i--) {
1229 const Actor *actor = game->GetPC(i, true);
1230 if (HasItemCore(&actor->inventory, parameters->string0Parameter, IE_INV_ITEM_IDENTIFIED) ) {
1231 return 1;
1232 }
1233 }
1234 return 0;
1235 }
1236
InventoryFull(Scriptable * Sender,const Trigger * parameters)1237 int GameScript::InventoryFull( Scriptable *Sender, const Trigger *parameters)
1238 {
1239 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
1240 if (!tar || tar->Type!=ST_ACTOR) {
1241 return 0;
1242 }
1243 const Actor *actor = (const Actor *) tar;
1244 if (actor->inventory.FindCandidateSlot(SLOT_INVENTORY, 0) == -1) {
1245 return 1;
1246 }
1247 return 0;
1248 }
1249
HasInnateAbility(Scriptable * Sender,const Trigger * parameters)1250 int GameScript::HasInnateAbility(Scriptable *Sender, const Trigger *parameters)
1251 {
1252 Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
1253 if (!tar || tar->Type!=ST_ACTOR) {
1254 return 0;
1255 }
1256 Actor *actor = (Actor *) tar;
1257 if (parameters->string0Parameter[0]) {
1258 return actor->spellbook.HaveSpell(parameters->string0Parameter, 0);
1259 }
1260 return actor->spellbook.HaveSpell(parameters->int0Parameter, 0);
1261 }
1262
HaveSpell(Scriptable * Sender,const Trigger * parameters)1263 int GameScript::HaveSpell(Scriptable *Sender, const Trigger *parameters)
1264 {
1265 if (Sender->Type!=ST_ACTOR) {
1266 return 0;
1267 }
1268
1269 if (parameters->int0Parameter == 0 && Sender->LastMarkedSpell == 0) {
1270 return false;
1271 }
1272
1273 Actor *actor = (Actor *) Sender;
1274 if (parameters->string0Parameter[0]) {
1275 return actor->spellbook.HaveSpell(parameters->string0Parameter, 0);
1276 }
1277 int spellNum = parameters->int0Parameter;
1278 if (!spellNum) spellNum = Sender->LastMarkedSpell;
1279 return actor->spellbook.HaveSpell(spellNum, 0);
1280 }
1281
HaveAnySpells(Scriptable * Sender,const Trigger *)1282 int GameScript::HaveAnySpells(Scriptable *Sender, const Trigger */*parameters*/)
1283 {
1284 if (Sender->Type!=ST_ACTOR) {
1285 return 0;
1286 }
1287 Actor *actor = (Actor *) Sender;
1288 return actor->spellbook.HaveSpell("", 0);
1289 }
1290
HaveSpellParty(Scriptable *,const Trigger * parameters)1291 int GameScript::HaveSpellParty(Scriptable */*Sender*/, const Trigger *parameters)
1292 {
1293 const Game *game = core->GetGame();
1294
1295 int i = game->GetPartySize(true);
1296
1297 if (parameters->string0Parameter[0]) {
1298 while(i--) {
1299 Actor *actor = game->GetPC(i, true);
1300 if (actor->spellbook.HaveSpell(parameters->string0Parameter, 0) ) {
1301 return 1;
1302 }
1303 }
1304 } else {
1305 while(i--) {
1306 Actor *actor = game->GetPC(i, true);
1307 if (actor->spellbook.HaveSpell(parameters->int0Parameter, 0) ) {
1308 return 1;
1309 }
1310 }
1311 }
1312 return 0;
1313 }
1314
KnowSpell(Scriptable * Sender,const Trigger * parameters)1315 int GameScript::KnowSpell(Scriptable *Sender, const Trigger *parameters)
1316 {
1317 if (Sender->Type!=ST_ACTOR) {
1318 return 0;
1319 }
1320 const Actor *actor = (const Actor *) Sender;
1321 if (parameters->string0Parameter[0]) {
1322 return actor->spellbook.KnowSpell(parameters->string0Parameter);
1323 }
1324 return actor->spellbook.KnowSpell(parameters->int0Parameter);
1325 }
1326
True(Scriptable *,const Trigger *)1327 int GameScript::True(Scriptable */* Sender*/, const Trigger */*parameters*/)
1328 {
1329 return 1;
1330 }
1331
1332 //in fact this could be used only on Sender, but we want to enhance these
1333 //triggers and actions to accept an object argument whenever possible.
1334 //0 defaults to Myself (Sender)
NumTimesTalkedTo(Scriptable * Sender,const Trigger * parameters)1335 int GameScript::NumTimesTalkedTo(Scriptable *Sender, const Trigger *parameters)
1336 {
1337 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1338 if (!scr) {
1339 scr = Sender;
1340 }
1341 if (scr->Type != ST_ACTOR) {
1342 return 0;
1343 }
1344 const Actor *actor = (const Actor *) scr;
1345 return actor->TalkCount == (ieDword) parameters->int0Parameter ? 1 : 0;
1346 }
1347
NumTimesTalkedToGT(Scriptable * Sender,const Trigger * parameters)1348 int GameScript::NumTimesTalkedToGT(Scriptable *Sender, const Trigger *parameters)
1349 {
1350 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1351 if (!scr) {
1352 scr = Sender;
1353 }
1354 if (scr->Type != ST_ACTOR) {
1355 return 0;
1356 }
1357 const Actor *actor = (const Actor *) scr;
1358 return actor->TalkCount > (ieDword) parameters->int0Parameter ? 1 : 0;
1359 }
1360
NumTimesTalkedToLT(Scriptable * Sender,const Trigger * parameters)1361 int GameScript::NumTimesTalkedToLT(Scriptable *Sender, const Trigger *parameters)
1362 {
1363 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1364 if (!scr) {
1365 scr = Sender;
1366 }
1367 if (scr->Type != ST_ACTOR) {
1368 return 0;
1369 }
1370 const Actor *actor = (const Actor *) scr;
1371 return actor->TalkCount < (ieDword) parameters->int0Parameter ? 1 : 0;
1372 }
1373
NumTimesInteracted(Scriptable * Sender,const Trigger * parameters)1374 int GameScript::NumTimesInteracted(Scriptable *Sender, const Trigger *parameters)
1375 {
1376 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1377 if (!scr) {
1378 scr = Sender;
1379 }
1380 if (scr->Type != ST_ACTOR) {
1381 return 0;
1382 }
1383 const Actor *actor = (const Actor *) scr;
1384 ieDword npcid = parameters->int0Parameter;
1385 if (npcid>=MAX_INTERACT) return 0;
1386 if (!actor->PCStats) return 0;
1387 return actor->PCStats->Interact[npcid] == (ieDword) parameters->int1Parameter ? 1 : 0;
1388 }
1389
NumTimesInteractedGT(Scriptable * Sender,const Trigger * parameters)1390 int GameScript::NumTimesInteractedGT(Scriptable *Sender, const Trigger *parameters)
1391 {
1392 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1393 if (!scr) {
1394 scr = Sender;
1395 }
1396 if (scr->Type != ST_ACTOR) {
1397 return 0;
1398 }
1399 const Actor *actor = (const Actor *) scr;
1400 ieDword npcid = parameters->int0Parameter;
1401 if (npcid>=MAX_INTERACT) return 0;
1402 if (!actor->PCStats) return 0;
1403 return actor->PCStats->Interact[npcid] > (ieDword) parameters->int1Parameter ? 1 : 0;
1404 }
1405
NumTimesInteractedLT(Scriptable * Sender,const Trigger * parameters)1406 int GameScript::NumTimesInteractedLT(Scriptable *Sender, const Trigger *parameters)
1407 {
1408 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1409 if (!scr) {
1410 scr = Sender;
1411 }
1412 if (scr->Type != ST_ACTOR) {
1413 return 0;
1414 }
1415 const Actor *actor = (const Actor *) scr;
1416 ieDword npcid = parameters->int0Parameter;
1417 if (npcid>=MAX_INTERACT) return 0;
1418 if (!actor->PCStats) return 0;
1419 return actor->PCStats->Interact[npcid] < (ieDword) parameters->int1Parameter ? 1 : 0;
1420 }
1421
1422 //GemRB specific
1423 //interacting npc counts were restricted to 24
1424 //gemrb will increase a local variable in the interacting npc, with the scriptname of the
1425 //target npc
NumTimesInteractedObject(Scriptable * Sender,const Trigger * parameters)1426 int GameScript::NumTimesInteractedObject(Scriptable *Sender, const Trigger *parameters)
1427 {
1428 if (Sender->Type != ST_ACTOR) {
1429 return 0;
1430 }
1431
1432 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1433 if (!scr) {
1434 return 0;
1435 }
1436 if (scr->Type != ST_ACTOR) {
1437 return 0;
1438 }
1439 const Actor *tar = (const Actor *) scr;
1440 return CheckVariable(Sender, tar->GetScriptName(), "LOCALS") == (ieDword) parameters->int0Parameter ? 1 : 0;
1441 }
1442
NumTimesInteractedObjectGT(Scriptable * Sender,const Trigger * parameters)1443 int GameScript::NumTimesInteractedObjectGT(Scriptable *Sender, const Trigger *parameters)
1444 {
1445 if (Sender->Type != ST_ACTOR) {
1446 return 0;
1447 }
1448
1449 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1450 if (!scr) {
1451 return 0;
1452 }
1453 if (scr->Type != ST_ACTOR) {
1454 return 0;
1455 }
1456 const Actor *tar = (const Actor *) scr;
1457 return CheckVariable(Sender, tar->GetScriptName(), "LOCALS") > (ieDword) parameters->int0Parameter ? 1 : 0;
1458 }
1459
NumTimesInteractedObjectLT(Scriptable * Sender,const Trigger * parameters)1460 int GameScript::NumTimesInteractedObjectLT(Scriptable *Sender, const Trigger *parameters)
1461 {
1462 if (Sender->Type != ST_ACTOR) {
1463 return 0;
1464 }
1465
1466 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1467 if (!scr) {
1468 return 0;
1469 }
1470 if (scr->Type != ST_ACTOR) {
1471 return 0;
1472 }
1473 const Actor *tar = (const Actor *) scr;
1474 return CheckVariable(Sender, tar->GetScriptName(), "LOCALS") < (ieDword) parameters->int0Parameter ? 1 : 0;
1475 }
1476
ObjectActionListEmpty(Scriptable * Sender,const Trigger * parameters)1477 int GameScript::ObjectActionListEmpty(Scriptable *Sender, const Trigger *parameters)
1478 {
1479 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1480 if (!scr) {
1481 return 0;
1482 }
1483
1484 // added CurrentAction as part of blocking action fixes
1485 if (scr->GetCurrentAction() || scr->GetNextAction()) {
1486 return 0;
1487 }
1488 return 1;
1489 }
1490
ActionListEmpty(Scriptable * Sender,const Trigger *)1491 int GameScript::ActionListEmpty(Scriptable *Sender, const Trigger */*parameters*/)
1492 {
1493 // added CurrentAction as part of blocking action fixes
1494 if (Sender->GetCurrentAction() || Sender->GetNextAction()) {
1495 return 0;
1496 }
1497 return 1;
1498 }
1499
False(Scriptable *,const Trigger *)1500 int GameScript::False(Scriptable */*Sender*/, const Trigger */*parameters*/)
1501 {
1502 return 0;
1503 }
1504
1505 /* i guess this is a range of circle edges (instead of centers) */
PersonalSpaceDistance(Scriptable * Sender,const Trigger * parameters)1506 int GameScript::PersonalSpaceDistance(Scriptable *Sender, const Trigger *parameters)
1507 {
1508 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1509 if (!scr) {
1510 return 0;
1511 }
1512
1513 if (WithinPersonalRange(scr, Sender, parameters->int0Parameter)) {
1514 return 1;
1515 }
1516 return 0;
1517 }
1518
Range(Scriptable * Sender,const Trigger * parameters)1519 int GameScript::Range(Scriptable *Sender, const Trigger *parameters)
1520 {
1521 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1522 if (!scr) {
1523 return 0;
1524 }
1525 if (Sender->GetCurrentArea() != scr->GetCurrentArea()) {
1526 return 0;
1527 }
1528 if (Sender->Type == ST_ACTOR) {
1529 Sender->LastMarked = scr->GetGlobalID();
1530 }
1531 int distance = SquaredMapDistance(Sender, scr);
1532 bool matched = DiffCore(distance, (parameters->int0Parameter + 1) * (parameters->int0Parameter + 1), parameters->int1Parameter);
1533 if (matched) {
1534 Sender->SetLastTrigger(trigger_range, scr->GetGlobalID());
1535 }
1536 return matched;
1537 }
1538
InLine(Scriptable * Sender,const Trigger * parameters)1539 int GameScript::InLine(Scriptable *Sender, const Trigger *parameters)
1540 {
1541 const Map *map = Sender->GetCurrentArea();
1542 if (!map) {
1543 return 0;
1544 }
1545
1546 const Scriptable *scr1 = GetActorFromObject(Sender, parameters->objectParameter);
1547 if (!scr1) {
1548 return 0;
1549 }
1550
1551 //looking for a scriptable by scriptname only
1552 const Scriptable *scr2 = map->GetActor(parameters->string0Parameter, 0);
1553 if (!scr2) {
1554 scr2 = GetActorObject(map->GetTileMap(), parameters->string0Parameter);
1555 }
1556 if (!scr2) {
1557 return 0;
1558 }
1559
1560 double fdm1 = SquaredDistance(Sender, scr1);
1561 double fdm2 = SquaredDistance(Sender, scr2);
1562 double fd12 = SquaredDistance(scr1, scr2);
1563 double dm1 = sqrt(fdm1);
1564 double dm2 = sqrt(fdm2);
1565
1566 if (fdm1>fdm2 || fd12>fdm2) {
1567 return 0;
1568 }
1569 double angle = acos(( fdm2 + fdm1 - fd12 ) / (2*dm1*dm2));
1570 if (angle*180.0*M_PI<30.0) return 1;
1571 return 0;
1572 }
1573
1574 //PST
AtLocation(Scriptable * Sender,const Trigger * parameters)1575 int GameScript::AtLocation( Scriptable *Sender, const Trigger *parameters)
1576 {
1577 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
1578 if (!tar) {
1579 return 0;
1580 }
1581 if ( (tar->Pos.x==parameters->pointParameter.x) &&
1582 (tar->Pos.y==parameters->pointParameter.y) ) {
1583 return 1;
1584 }
1585 return 0;
1586 }
1587
1588 //in pst this is a point
1589 //in iwd2 this is not a point
1590 // and -2,-2 is treated specially in iwd2 (Jorun in Targos)
NearLocation(Scriptable * Sender,const Trigger * parameters)1591 int GameScript::NearLocation(Scriptable *Sender, const Trigger *parameters)
1592 {
1593 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1594 if (!scr) {
1595 return 0;
1596 }
1597 if (parameters->pointParameter.isnull()) {
1598 int distance;
1599 if (parameters->int0Parameter < 0) { // use Sender's position
1600 distance = PersonalDistance(Sender, scr);
1601 } else {
1602 Point p((short) parameters->int0Parameter, (short) parameters->int1Parameter);
1603 distance = PersonalDistance(p, scr);
1604 }
1605 if (distance <= (parameters->int2Parameter * VOODOO_NEARLOC_F)) {
1606 return 1;
1607 }
1608 return 0;
1609 }
1610 //personaldistance is needed for modron constructs in PST maze
1611 int distance = PersonalDistance(parameters->pointParameter, scr);
1612 if (distance <= (parameters->int0Parameter * VOODOO_NEARLOC_F)) {
1613 return 1;
1614 }
1615 return 0;
1616 }
1617
1618 // EEs extend this to NearSavedLocation(O:Object*,S:Global*,I:Range*)
NearSavedLocation(Scriptable * Sender,const Trigger * parameters)1619 int GameScript::NearSavedLocation(Scriptable *Sender, const Trigger *parameters)
1620 {
1621 if (Sender->Type!=ST_ACTOR) {
1622 return 0;
1623 }
1624 if (core->HasFeature(GF_HAS_KAPUTZ)) {
1625 // TODO: we don't understand how this works in pst yet
1626 Log(ERROR, "GameScript", "Aborting NearSavedLocation! Don't know what to do!");
1627 return 1;
1628 }
1629 const Actor *actor = (const Actor *) Sender;
1630 Point p;
1631 if ((signed) actor->GetStat(IE_SAVEDXPOS) <= 0 && (signed) actor->GetStat(IE_SAVEDYPOS) <= 0) {
1632 p = actor->HomeLocation;
1633 } else {
1634 p.x = (short) actor->GetStat(IE_SAVEDXPOS);
1635 p.y = (short) actor->GetStat(IE_SAVEDYPOS);
1636 }
1637 // should this be PersonalDistance?
1638 int distance = Distance(p, Sender);
1639 if (distance <= (parameters->int0Parameter * VOODOO_NEARLOC_F)) {
1640 return 1;
1641 }
1642 return 0;
1643 }
1644
Or(Scriptable *,const Trigger * parameters)1645 int GameScript::Or(Scriptable */*Sender*/, const Trigger *parameters)
1646 {
1647 return parameters->int0Parameter;
1648 }
1649
TriggerTrigger(Scriptable * Sender,const Trigger * parameters)1650 int GameScript::TriggerTrigger(Scriptable *Sender, const Trigger *parameters)
1651 {
1652 return Sender->MatchTrigger(trigger_trigger, parameters->int0Parameter);
1653 }
1654
WalkedToTrigger(Scriptable * Sender,const Trigger * parameters)1655 int GameScript::WalkedToTrigger(Scriptable *Sender, const Trigger *parameters)
1656 {
1657 return Sender->MatchTriggerWithObject(trigger_walkedtotrigger, parameters->objectParameter);
1658 }
1659
Clicked(Scriptable * Sender,const Trigger * parameters)1660 int GameScript::Clicked(Scriptable *Sender, const Trigger *parameters)
1661 {
1662 return Sender->MatchTriggerWithObject(trigger_clicked, parameters->objectParameter);
1663 }
1664
Disarmed(Scriptable * Sender,const Trigger * parameters)1665 int GameScript::Disarmed(Scriptable *Sender, const Trigger *parameters)
1666 {
1667 return Sender->MatchTriggerWithObject(trigger_disarmed, parameters->objectParameter);
1668 }
1669
1670 //stealing from a store failed, owner triggered
StealFailed(Scriptable * Sender,const Trigger * parameters)1671 int GameScript::StealFailed(Scriptable *Sender, const Trigger *parameters)
1672 {
1673 return Sender->MatchTriggerWithObject(trigger_stealfailed, parameters->objectParameter);
1674 }
1675
PickpocketFailed(Scriptable * Sender,const Trigger * parameters)1676 int GameScript::PickpocketFailed(Scriptable *Sender, const Trigger *parameters)
1677 {
1678 return Sender->MatchTriggerWithObject(trigger_pickpocketfailed, parameters->objectParameter);
1679 }
1680
PickLockFailed(Scriptable * Sender,const Trigger * parameters)1681 int GameScript::PickLockFailed(Scriptable *Sender, const Trigger *parameters)
1682 {
1683 return Sender->MatchTriggerWithObject(trigger_picklockfailed, parameters->objectParameter);
1684 }
1685
OpenFailed(Scriptable * Sender,const Trigger * parameters)1686 int GameScript::OpenFailed(Scriptable *Sender, const Trigger *parameters)
1687 {
1688 return Sender->MatchTriggerWithObject(trigger_failedtoopen, parameters->objectParameter);
1689 }
1690
DisarmFailed(Scriptable * Sender,const Trigger * parameters)1691 int GameScript::DisarmFailed(Scriptable *Sender, const Trigger *parameters)
1692 {
1693 return Sender->MatchTriggerWithObject(trigger_disarmfailed, parameters->objectParameter);
1694 }
1695
1696 //opened for doors/containers
Opened(Scriptable * Sender,const Trigger * parameters)1697 int GameScript::Opened(Scriptable *Sender, const Trigger *parameters)
1698 {
1699 return Sender->MatchTriggerWithObject(trigger_opened, parameters->objectParameter);
1700 }
1701
HarmlessOpened(Scriptable * Sender,const Trigger * parameters)1702 int GameScript::HarmlessOpened(Scriptable *Sender, const Trigger *parameters)
1703 {
1704 return Sender->MatchTriggerWithObject(trigger_harmlessopened, parameters->objectParameter);
1705 }
1706
1707 //closed for doors
Closed(Scriptable * Sender,const Trigger * parameters)1708 int GameScript::Closed(Scriptable *Sender, const Trigger *parameters)
1709 {
1710 return Sender->MatchTriggerWithObject(trigger_closed, parameters->objectParameter);
1711 }
1712
HarmlessClosed(Scriptable * Sender,const Trigger * parameters)1713 int GameScript::HarmlessClosed(Scriptable *Sender, const Trigger *parameters)
1714 {
1715 return Sender->MatchTriggerWithObject(trigger_harmlessclosed, parameters->objectParameter);
1716 }
1717
1718 //unlocked for doors/containers (using lastUnlocked)
Unlocked(Scriptable * Sender,const Trigger * parameters)1719 int GameScript::Unlocked(Scriptable *Sender, const Trigger *parameters)
1720 {
1721 return Sender->MatchTriggerWithObject(trigger_unlocked, parameters->objectParameter);
1722 }
1723
Entered(Scriptable * Sender,const Trigger * parameters)1724 int GameScript::Entered(Scriptable *Sender, const Trigger *parameters)
1725 {
1726 return Sender->MatchTriggerWithObject(trigger_entered, parameters->objectParameter);
1727 }
1728
HarmlessEntered(Scriptable * Sender,const Trigger * parameters)1729 int GameScript::HarmlessEntered(Scriptable *Sender, const Trigger *parameters)
1730 {
1731 return Sender->MatchTriggerWithObject(trigger_harmlessentered, parameters->objectParameter);
1732 }
1733
IsOverMe(Scriptable * Sender,const Trigger * parameters)1734 int GameScript::IsOverMe(Scriptable *Sender, const Trigger *parameters)
1735 {
1736 if (Sender->Type != ST_PROXIMITY) {
1737 return 0;
1738 }
1739 const Highlightable *trap = (Highlightable *) Sender;
1740
1741 Targets *tgts = GetAllObjects(Sender->GetCurrentArea(), Sender, parameters->objectParameter, GA_NO_DEAD|GA_NO_UNSCHEDULED);
1742 int ret = 0;
1743 if (tgts) {
1744 targetlist::iterator m;
1745 const targettype *tt = tgts->GetFirstTarget(m, ST_ACTOR);
1746 while (tt) {
1747 const Actor *actor = (Actor *) tt->actor;
1748 if (trap->IsOver(actor->Pos)) {
1749 ret = 1;
1750 break;
1751 }
1752 tt = tgts->GetNextTarget(m, ST_ACTOR);
1753 }
1754 }
1755 delete tgts;
1756 return ret;
1757 }
1758
1759 //this function is different in every engines, if you use a string0parameter
1760 //then it will be considered as a variable check
1761 //you can also use an object parameter (like in iwd)
Dead(Scriptable * Sender,const Trigger * parameters)1762 int GameScript::Dead(Scriptable *Sender, const Trigger *parameters)
1763 {
1764 if (parameters->string0Parameter[0]) {
1765 ieDword value;
1766 ieVariable Variable;
1767 size_t len;
1768
1769 if (core->HasFeature( GF_HAS_KAPUTZ )) {
1770 len = snprintf(Variable,sizeof(ieVariable),"%s_DEAD",parameters->string0Parameter);
1771 value = CheckVariable( Sender, Variable, "KAPUTZ");
1772 } else {
1773 len = snprintf(Variable, sizeof(ieVariable), core->GetDeathVarFormat(), parameters->string0Parameter);
1774 value = CheckVariable( Sender, Variable, "GLOBAL" );
1775 }
1776 if (len > sizeof(ieVariable)) {
1777 Log(ERROR, "GameScript", "Scriptname %s (sender: %s) is too long for generating death globals!", parameters->string0Parameter, Sender->GetScriptName());
1778 }
1779 if (value>0) {
1780 return 1;
1781 }
1782 return 0;
1783 }
1784 const Scriptable *target = GetActorFromObject(Sender, parameters->objectParameter);
1785 if (!target) {
1786 return 1;
1787 }
1788 if (target->Type != ST_ACTOR) {
1789 return 1;
1790 }
1791 const Actor *actor = (const Actor *) target;
1792 // actors not meeting AreaDifficulty get deleted before we have to worry about them
1793 if (actor->GetStat( IE_STATE_ID ) & STATE_DEAD) {
1794 return 1;
1795 }
1796 return 0;
1797 }
1798
CreatureHidden(Scriptable * Sender,const Trigger * parameters)1799 int GameScript::CreatureHidden(Scriptable *Sender, const Trigger *parameters)
1800 {
1801 Scriptable *target = GetActorFromObject(Sender, parameters->objectParameter);
1802 if (!target) {
1803 return 0;
1804 }
1805 if (target->Type != ST_ACTOR) {
1806 return 0;
1807 }
1808 const Actor *act = (const Actor *) target;
1809
1810 //this stuff is not completely clear, but HoW has a flag for this
1811 //and GemRB uses the avatarremoval stat for it.
1812 //HideCreature also sets this stat, so...
1813 if (act->GetStat(IE_AVATARREMOVAL)) {
1814 return 1;
1815 }
1816
1817 if (act->GetInternalFlag()&IF_VISIBLE) {
1818 return 0;
1819 }
1820 return 1;
1821 }
BecameVisible(Scriptable * Sender,const Trigger *)1822 int GameScript::BecameVisible(Scriptable *Sender, const Trigger */*parameters*/)
1823 {
1824 return Sender->MatchTrigger(trigger_becamevisible);
1825 }
1826
Die(Scriptable * Sender,const Trigger *)1827 int GameScript::Die(Scriptable *Sender, const Trigger */*parameters*/)
1828 {
1829 return Sender->MatchTrigger(trigger_die);
1830 }
1831
Died(Scriptable * Sender,const Trigger * parameters)1832 int GameScript::Died(Scriptable *Sender, const Trigger *parameters)
1833 {
1834 return Sender->MatchTriggerWithObject(trigger_died, parameters->objectParameter);
1835 }
1836
PartyMemberDied(Scriptable * Sender,const Trigger * parameters)1837 int GameScript::PartyMemberDied(Scriptable *Sender, const Trigger *parameters)
1838 {
1839 return Sender->MatchTriggerWithObject(trigger_partymemberdied, parameters->objectParameter);
1840 }
1841
NamelessBitTheDust(Scriptable * Sender,const Trigger *)1842 int GameScript::NamelessBitTheDust(Scriptable *Sender, const Trigger */*parameters*/)
1843 {
1844 return Sender->MatchTrigger(trigger_namelessbitthedust);
1845 }
1846
Killed(Scriptable * Sender,const Trigger * parameters)1847 int GameScript::Killed(Scriptable *Sender, const Trigger *parameters)
1848 {
1849 return Sender->MatchTriggerWithObject(trigger_killed, parameters->objectParameter);
1850 }
1851
Race(Scriptable * Sender,const Trigger * parameters)1852 int GameScript::Race(Scriptable *Sender, const Trigger *parameters)
1853 {
1854 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1855 if (!scr) {
1856 return 0;
1857 }
1858 if (scr->Type != ST_ACTOR) {
1859 return 0;
1860 }
1861 const Actor *actor = (const Actor *) scr;
1862 bool matched = ID_Race(actor, parameters->int0Parameter);
1863 if (matched) {
1864 Sender->SetLastTrigger(trigger_race, actor->GetGlobalID());
1865 }
1866 return matched;
1867 }
1868
Gender(Scriptable * Sender,const Trigger * parameters)1869 int GameScript::Gender(Scriptable *Sender, const Trigger *parameters)
1870 {
1871 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1872 if (!scr) {
1873 return 0;
1874 }
1875 if (scr->Type != ST_ACTOR) {
1876 return 0;
1877 }
1878 const Actor *actor = (const Actor *) scr;
1879 bool matched = ID_Gender(actor, parameters->int0Parameter);
1880 if (matched) {
1881 Sender->SetLastTrigger(trigger_gender, actor->GetGlobalID());
1882 }
1883 return matched;
1884 }
1885
HP(Scriptable * Sender,const Trigger * parameters)1886 int GameScript::HP(Scriptable *Sender, const Trigger *parameters)
1887 {
1888 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1889 if (!scr) {
1890 return 0;
1891 }
1892 if (scr->Type != ST_ACTOR) {
1893 return 0;
1894 }
1895 const Actor *actor = (const Actor *) scr;
1896 if ((signed) actor->GetBase(IE_HITPOINTS) == parameters->int0Parameter) {
1897 Sender->SetLastTrigger(trigger_hpgt, actor->GetGlobalID());
1898 return 1;
1899 }
1900 return 0;
1901 }
1902
HPGT(Scriptable * Sender,const Trigger * parameters)1903 int GameScript::HPGT(Scriptable *Sender, const Trigger *parameters)
1904 {
1905 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1906 if (!scr) {
1907 return 0;
1908 }
1909 if (scr->Type != ST_ACTOR) {
1910 return 0;
1911 }
1912 const Actor *actor = (const Actor *) scr;
1913 if ((signed) actor->GetBase(IE_HITPOINTS) > parameters->int0Parameter) {
1914 Sender->SetLastTrigger(trigger_hpgt, actor->GetGlobalID());
1915 return 1;
1916 }
1917 return 0;
1918 }
1919
HPLT(Scriptable * Sender,const Trigger * parameters)1920 int GameScript::HPLT(Scriptable *Sender, const Trigger *parameters)
1921 {
1922 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1923 if (!scr) {
1924 return 0;
1925 }
1926 if (scr->Type != ST_ACTOR) {
1927 return 0;
1928 }
1929 const Actor *actor = (const Actor *) scr;
1930 if ((signed) actor->GetBase(IE_HITPOINTS) < parameters->int0Parameter) {
1931 Sender->SetLastTrigger(trigger_hpgt, actor->GetGlobalID());
1932 return 1;
1933 }
1934 return 0;
1935 }
1936
1937 //these triggers work on the current damage (not the last damage)
1938 //actually, they use lastdamage
DamageTaken(Scriptable * Sender,const Trigger * parameters)1939 int GameScript::DamageTaken(Scriptable *Sender, const Trigger *parameters)
1940 {
1941 if (Sender->Type!=ST_ACTOR) {
1942 return 0;
1943 }
1944 const Actor *actor = (const Actor *) Sender;
1945 int damage = actor->LastDamage;
1946 if (damage == parameters->int0Parameter) {
1947 return 1;
1948 }
1949 return 0;
1950 }
1951
DamageTakenGT(Scriptable * Sender,const Trigger * parameters)1952 int GameScript::DamageTakenGT(Scriptable *Sender, const Trigger *parameters)
1953 {
1954 if (Sender->Type!=ST_ACTOR) {
1955 return 0;
1956 }
1957 const Actor *actor = (const Actor *) Sender;
1958 int damage = actor->LastDamage;
1959 if (damage > parameters->int0Parameter) {
1960 return 1;
1961 }
1962 return 0;
1963 }
1964
DamageTakenLT(Scriptable * Sender,const Trigger * parameters)1965 int GameScript::DamageTakenLT(Scriptable *Sender, const Trigger *parameters)
1966 {
1967 if (Sender->Type!=ST_ACTOR) {
1968 return 0;
1969 }
1970 const Actor *actor = (const Actor *) Sender;
1971 int damage = actor->LastDamage;
1972 if (damage < parameters->int0Parameter) {
1973 return 1;
1974 }
1975 return 0;
1976 }
1977
HPLost(Scriptable * Sender,const Trigger * parameters)1978 int GameScript::HPLost(Scriptable *Sender, const Trigger *parameters)
1979 {
1980 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1981 if (!scr) {
1982 return 0;
1983 }
1984 if (scr->Type != ST_ACTOR) {
1985 return 0;
1986 }
1987 const Actor *actor = (const Actor *) scr;
1988 //max-current
1989 if ((signed) actor->GetStat(IE_MAXHITPOINTS) - (signed) actor->GetBase(IE_HITPOINTS) == parameters->int0Parameter) {
1990 return 1;
1991 }
1992 return 0;
1993 }
1994
HPLostGT(Scriptable * Sender,const Trigger * parameters)1995 int GameScript::HPLostGT(Scriptable *Sender, const Trigger *parameters)
1996 {
1997 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
1998 if (!scr) {
1999 return 0;
2000 }
2001 if (scr->Type != ST_ACTOR) {
2002 return 0;
2003 }
2004 const Actor *actor = (const Actor *) scr;
2005 //max-current
2006 if ((signed) actor->GetStat(IE_MAXHITPOINTS) - (signed) actor->GetBase(IE_HITPOINTS) > parameters->int0Parameter) {
2007 return 1;
2008 }
2009 return 0;
2010 }
2011
HPLostLT(Scriptable * Sender,const Trigger * parameters)2012 int GameScript::HPLostLT(Scriptable *Sender, const Trigger *parameters)
2013 {
2014 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
2015 if (!scr) {
2016 return 0;
2017 }
2018 if (scr->Type != ST_ACTOR) {
2019 return 0;
2020 }
2021 const Actor *actor = (const Actor *) scr;
2022 //max-current
2023 if ((signed) actor->GetStat(IE_MAXHITPOINTS) - (signed) actor->GetBase(IE_HITPOINTS) < parameters->int0Parameter) {
2024 return 1;
2025 }
2026 return 0;
2027 }
2028
HPPercent(Scriptable * Sender,const Trigger * parameters)2029 int GameScript::HPPercent(Scriptable *Sender, const Trigger *parameters)
2030 {
2031 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
2032 if (!scr) {
2033 return 0;
2034 }
2035 if (GetHPPercent( scr ) == parameters->int0Parameter) {
2036 Sender->SetLastTrigger(trigger_hpgt, scr->GetGlobalID());
2037 return 1;
2038 }
2039 return 0;
2040 }
2041
HPPercentGT(Scriptable * Sender,const Trigger * parameters)2042 int GameScript::HPPercentGT(Scriptable *Sender, const Trigger *parameters)
2043 {
2044 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
2045 if (!scr) {
2046 return 0;
2047 }
2048 if (GetHPPercent( scr ) > parameters->int0Parameter) {
2049 Sender->SetLastTrigger(trigger_hpgt, scr->GetGlobalID());
2050 return 1;
2051 }
2052 return 0;
2053 }
2054
HPPercentLT(Scriptable * Sender,const Trigger * parameters)2055 int GameScript::HPPercentLT(Scriptable *Sender, const Trigger *parameters)
2056 {
2057 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
2058 if (!scr) {
2059 return 0;
2060 }
2061 if (GetHPPercent( scr ) < parameters->int0Parameter) {
2062 Sender->SetLastTrigger(trigger_hpgt, scr->GetGlobalID());
2063 return 1;
2064 }
2065 return 0;
2066 }
2067
XP(Scriptable * Sender,const Trigger * parameters)2068 int GameScript::XP(Scriptable *Sender, const Trigger *parameters)
2069 {
2070 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
2071 if (!scr) {
2072 return 0;
2073 }
2074 if (scr->Type != ST_ACTOR) {
2075 return 0;
2076 }
2077 const Actor *actor = (const Actor *) scr;
2078 if (actor->GetStat( IE_XP ) == (unsigned) parameters->int0Parameter) {
2079 return 1;
2080 }
2081 return 0;
2082 }
2083
XPGT(Scriptable * Sender,const Trigger * parameters)2084 int GameScript::XPGT(Scriptable *Sender, const Trigger *parameters)
2085 {
2086 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
2087 if (!scr) {
2088 return 0;
2089 }
2090 if (scr->Type != ST_ACTOR) {
2091 return 0;
2092 }
2093 const Actor *actor = (const Actor *) scr;
2094 if (actor->GetStat( IE_XP ) > (unsigned) parameters->int0Parameter) {
2095 return 1;
2096 }
2097 return 0;
2098 }
2099
XPLT(Scriptable * Sender,const Trigger * parameters)2100 int GameScript::XPLT(Scriptable *Sender, const Trigger *parameters)
2101 {
2102 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
2103 if (!scr) {
2104 return 0;
2105 }
2106 if (scr->Type != ST_ACTOR) {
2107 return 0;
2108 }
2109 const Actor *actor = (const Actor *) scr;
2110 if (actor->GetStat( IE_XP ) < (unsigned) parameters->int0Parameter) {
2111 return 1;
2112 }
2113 return 0;
2114 }
2115
CheckSkill(Scriptable * Sender,const Trigger * parameters)2116 int GameScript::CheckSkill(Scriptable *Sender, const Trigger *parameters)
2117 {
2118 const Scriptable *target = GetActorFromObject(Sender, parameters->objectParameter);
2119 if (!target) {
2120 return 0;
2121 }
2122 if (target->Type != ST_ACTOR) {
2123 return 0;
2124 }
2125 const Actor *actor = (const Actor *) target;
2126 int sk = actor->GetSkill(parameters->int1Parameter, true);
2127 if (sk<0) return 0;
2128 if (sk == parameters->int0Parameter) {
2129 return 1;
2130 }
2131 return 0;
2132 }
2133
CheckStat(Scriptable * Sender,const Trigger * parameters)2134 int GameScript::CheckStat(Scriptable *Sender, const Trigger *parameters)
2135 {
2136 const Scriptable *target = GetActorFromObject(Sender, parameters->objectParameter);
2137 if (!target) {
2138 return 0;
2139 }
2140 if (target->Type != ST_ACTOR) {
2141 return 0;
2142 }
2143 const Actor *actor = (const Actor *) target;
2144 if ((signed) actor->GetStat(parameters->int1Parameter) == parameters->int0Parameter) {
2145 Sender->SetLastTrigger(trigger_checkstat, actor->GetGlobalID());
2146 return 1;
2147 }
2148 return 0;
2149 }
2150
CheckSkillGT(Scriptable * Sender,const Trigger * parameters)2151 int GameScript::CheckSkillGT(Scriptable *Sender, const Trigger *parameters)
2152 {
2153 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2154 if (!tar || tar->Type != ST_ACTOR) {
2155 return 0;
2156 }
2157 const Actor *actor = (const Actor *) tar;
2158 int sk = actor->GetSkill(parameters->int1Parameter, true);
2159 if (sk<0) return 0;
2160 if (sk > parameters->int0Parameter) {
2161 Sender->SetLastTrigger(trigger_checkstat, actor->GetGlobalID());
2162 return 1;
2163 }
2164 return 0;
2165 }
2166
CheckStatGT(Scriptable * Sender,const Trigger * parameters)2167 int GameScript::CheckStatGT(Scriptable *Sender, const Trigger *parameters)
2168 {
2169 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2170 if (!tar || tar->Type != ST_ACTOR) {
2171 return 0;
2172 }
2173 const Actor *actor = (const Actor *) tar;
2174 if ((signed) actor->GetStat(parameters->int1Parameter) > parameters->int0Parameter) {
2175 Sender->SetLastTrigger(trigger_checkstat, actor->GetGlobalID());
2176 return 1;
2177 }
2178 return 0;
2179 }
2180
CheckSkillLT(Scriptable * Sender,const Trigger * parameters)2181 int GameScript::CheckSkillLT(Scriptable *Sender, const Trigger *parameters)
2182 {
2183 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2184 if (!tar || tar->Type != ST_ACTOR) {
2185 return 0;
2186 }
2187 const Actor *actor = (const Actor *) tar;
2188 int sk = actor->GetSkill(parameters->int1Parameter, true);
2189 if (sk<0) return 0;
2190 if (sk < parameters->int0Parameter) {
2191 return 1;
2192 }
2193 return 0;
2194 }
2195
CheckStatLT(Scriptable * Sender,const Trigger * parameters)2196 int GameScript::CheckStatLT(Scriptable *Sender, const Trigger *parameters)
2197 {
2198 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2199 if (!tar || tar->Type != ST_ACTOR) {
2200 return 0;
2201 }
2202 const Actor *actor = (const Actor *) tar;
2203 if ((signed) actor->GetStat(parameters->int1Parameter) < parameters->int0Parameter) {
2204 return 1;
2205 }
2206 return 0;
2207 }
2208
2209 /* i believe this trigger is the same as 'MarkObject' action
2210 except that if it cannot set the marked object, it returns false */
SetLastMarkedObject(Scriptable * Sender,const Trigger * parameters)2211 int GameScript::SetLastMarkedObject(Scriptable *Sender, const Trigger *parameters)
2212 {
2213 if (Sender->Type != ST_ACTOR) {
2214 return 0;
2215 }
2216 Actor *scr = (Actor *) Sender;
2217
2218 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2219 if (!tar || tar->Type != ST_ACTOR) {
2220 return 0;
2221 }
2222 scr->LastMarked = tar->GetGlobalID();
2223 return 1;
2224 }
2225
2226 // TODO: should there be any more failure modes?
2227 // iwd2 only
SetSpellTarget(Scriptable * Sender,const Trigger * parameters)2228 int GameScript::SetSpellTarget(Scriptable *Sender, const Trigger *parameters)
2229 {
2230 if (Sender->Type != ST_ACTOR) {
2231 return 0;
2232 }
2233 Actor *scr = (Actor *) Sender;
2234
2235 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2236 if (!tar) {
2237 // we got called with Nothing to invalidate the target
2238 scr->LastSpellTarget = 0;
2239 scr->LastTargetPos.empty();
2240 return 1;
2241 }
2242 scr->LastTargetPos.empty();
2243 scr->LastSpellTarget = tar->GetGlobalID();
2244 return 1;
2245 }
2246
IsSpellTargetValid(Scriptable * Sender,const Trigger * parameters)2247 int GameScript::IsSpellTargetValid(Scriptable *Sender, const Trigger *parameters)
2248 {
2249 if (Sender->Type != ST_ACTOR) {
2250 return 0;
2251 }
2252 Actor *scr = (Actor *) Sender;
2253
2254 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2255 if (!tar) {
2256 return 0;
2257 }
2258 const Actor *actor = nullptr;
2259 if (tar->Type == ST_ACTOR) {
2260 actor = (const Actor *) tar;
2261 }
2262
2263 int flags = parameters->int1Parameter;
2264 if (!(flags & MSO_IGNORE_NULL) && !actor) {
2265 return 0;
2266 }
2267 if (!(flags & MSO_IGNORE_INVALID) && actor && actor->InvalidSpellTarget() ) {
2268 return 0;
2269 }
2270 int splnum = parameters->int0Parameter;
2271 if (!(flags & MSO_IGNORE_HAVE) && !scr->spellbook.HaveSpell(splnum, 0) ) {
2272 return 0;
2273 }
2274 int range;
2275 if ((flags & MSO_IGNORE_RANGE) || !actor) {
2276 range = 0;
2277 } else {
2278 range = Distance(scr, actor);
2279 }
2280 if (!(flags & MSO_IGNORE_INVALID) && actor && actor->InvalidSpellTarget(splnum, scr, range)) {
2281 return 0;
2282 }
2283 return 1;
2284 }
2285
2286 //This trigger seems to always return true for actors...
2287 //Always manages to set spell to 0, otherwise it sets if there was nothing set earlier
SetMarkedSpell_Trigger(Scriptable * Sender,const Trigger * parameters)2288 int GameScript::SetMarkedSpell_Trigger(Scriptable *Sender, const Trigger *parameters)
2289 {
2290 Action *params = new Action(true);
2291 params->int0Parameter = parameters->int0Parameter;
2292 GameScript::SetMarkedSpell(Sender, params);
2293 delete params;
2294 return 1;
2295 }
2296
ForceMarkedSpell_Trigger(Scriptable * Sender,const Trigger * parameters)2297 int GameScript::ForceMarkedSpell_Trigger(Scriptable *Sender, const Trigger *parameters)
2298 {
2299 if (Sender->Type != ST_ACTOR) {
2300 return 0;
2301 }
2302 Actor *scr = (Actor *) Sender;
2303 scr->LastMarkedSpell = parameters->int0Parameter;
2304 return 1;
2305 }
2306
IsMarkedSpell(Scriptable * Sender,const Trigger * parameters)2307 int GameScript::IsMarkedSpell(Scriptable *Sender, const Trigger *parameters)
2308 {
2309 if (Sender->Type != ST_ACTOR) {
2310 return 0;
2311 }
2312 const Actor *scr = (const Actor *) Sender;
2313 return scr->LastMarkedSpell == parameters->int0Parameter;
2314 }
2315
2316
See(Scriptable * Sender,const Trigger * parameters)2317 int GameScript::See(Scriptable *Sender, const Trigger *parameters)
2318 {
2319 int see = SeeCore(Sender, parameters, 0);
2320 return see;
2321 }
2322
Detect(Scriptable * Sender,const Trigger * parameters)2323 int GameScript::Detect(Scriptable *Sender, const Trigger *parameters)
2324 {
2325 Trigger *params = new Trigger;
2326 params->int0Parameter = 1; //seedead/invis
2327 params->objectParameter = parameters->objectParameter;
2328 int see = SeeCore(Sender, params, 0);
2329 params->objectParameter = nullptr;
2330 params->Release();
2331 if (!see) {
2332 return 0;
2333 }
2334 return 1;
2335 }
2336
LOS(Scriptable * Sender,const Trigger * parameters)2337 int GameScript::LOS(Scriptable *Sender, const Trigger *parameters)
2338 {
2339 int see=SeeCore(Sender, parameters, 1);
2340 if (!see) {
2341 return 0;
2342 }
2343 return Range(Sender, parameters); //same as range
2344 }
2345
NumCreatures(Scriptable * Sender,const Trigger * parameters)2346 int GameScript::NumCreatures(Scriptable *Sender, const Trigger *parameters)
2347 {
2348 int value = GetObjectCount(Sender, parameters->objectParameter);
2349 bool matched = value == parameters->int0Parameter;
2350 // NOTE: in the original this is also supposed to set LastTarget, but it's not
2351 // clear to which of the possibly several actors, however
2352 // there are only two users and neither relies on LastTrigger, so we ignore it
2353 return matched;
2354 }
2355
NumCreaturesAtMyLevel(Scriptable * Sender,const Trigger * parameters)2356 int GameScript::NumCreaturesAtMyLevel(Scriptable *Sender, const Trigger *parameters)
2357 {
2358 if (Sender->Type != ST_ACTOR) {
2359 return 0;
2360 }
2361 int level = ((Actor *) Sender)->GetXPLevel(true);
2362 int value;
2363
2364 if (parameters->int0Parameter) {
2365 value = GetObjectLevelCount(Sender, parameters->objectParameter);
2366 } else {
2367 value = GetObjectCount(Sender, parameters->objectParameter);
2368 }
2369 return value == level;
2370 }
2371
NumCreaturesLT(Scriptable * Sender,const Trigger * parameters)2372 int GameScript::NumCreaturesLT(Scriptable *Sender, const Trigger *parameters)
2373 {
2374 int value = GetObjectCount(Sender, parameters->objectParameter);
2375 // see NOTE in NumCreatures; there are more users of LT and GT, but still none rely on LastTrigger
2376 return value < parameters->int0Parameter;
2377 }
2378
NumCreaturesLTMyLevel(Scriptable * Sender,const Trigger * parameters)2379 int GameScript::NumCreaturesLTMyLevel(Scriptable *Sender, const Trigger *parameters)
2380 {
2381 if (Sender->Type != ST_ACTOR) {
2382 return 0;
2383 }
2384 int level = ((Actor *) Sender)->GetXPLevel(true);
2385 int value;
2386
2387 if (parameters->int0Parameter) {
2388 value = GetObjectLevelCount(Sender, parameters->objectParameter);
2389 } else {
2390 value = GetObjectCount(Sender, parameters->objectParameter);
2391 }
2392 return value < level;
2393 }
2394
NumCreaturesGT(Scriptable * Sender,const Trigger * parameters)2395 int GameScript::NumCreaturesGT(Scriptable *Sender, const Trigger *parameters)
2396 {
2397 int value = GetObjectCount(Sender, parameters->objectParameter);
2398 // see NOTE in NumCreatures
2399 return value > parameters->int0Parameter;
2400 }
2401
NumCreaturesGTMyLevel(Scriptable * Sender,const Trigger * parameters)2402 int GameScript::NumCreaturesGTMyLevel(Scriptable *Sender, const Trigger *parameters)
2403 {
2404 if (Sender->Type != ST_ACTOR) {
2405 return 0;
2406 }
2407 int level = ((Actor *) Sender)->GetXPLevel(true);
2408 int value;
2409
2410 if (parameters->int0Parameter) {
2411 value = GetObjectLevelCount(Sender, parameters->objectParameter);
2412 } else {
2413 value = GetObjectCount(Sender, parameters->objectParameter);
2414 }
2415 return value > level;
2416 }
2417
NumCreatureVsParty(Scriptable * Sender,const Trigger * parameters)2418 int GameScript::NumCreatureVsParty(Scriptable *Sender, const Trigger *parameters)
2419 {
2420 //creating object on the spot
2421 Object *obj = parameters->objectParameter;
2422 if (!obj) {
2423 obj = new Object();
2424 }
2425 int value = GetObjectCount(Sender, obj);
2426 if (!obj->isNull()) obj->Release();
2427 value -= core->GetGame()->GetPartySize(true);
2428 return value == parameters->int0Parameter;
2429 }
2430
NumCreatureVsPartyGT(Scriptable * Sender,const Trigger * parameters)2431 int GameScript::NumCreatureVsPartyGT(Scriptable *Sender, const Trigger *parameters)
2432 {
2433 Object *obj = parameters->objectParameter;
2434 if (!obj) {
2435 obj = new Object();
2436 }
2437 int value = GetObjectCount(Sender, obj);
2438 if (!obj->isNull()) obj->Release();
2439 value -= core->GetGame()->GetPartySize(true);
2440 return value > parameters->int0Parameter;
2441 }
2442
NumCreatureVsPartyLT(Scriptable * Sender,const Trigger * parameters)2443 int GameScript::NumCreatureVsPartyLT(Scriptable *Sender, const Trigger *parameters)
2444 {
2445 Object *obj = parameters->objectParameter;
2446 if (!obj) {
2447 obj = new Object();
2448 }
2449 int value = GetObjectCount(Sender, obj);
2450 if (!obj->isNull()) obj->Release();
2451 value -= core->GetGame()->GetPartySize(true);
2452 return value < parameters->int0Parameter;
2453 }
2454
Morale(Scriptable * Sender,const Trigger * parameters)2455 int GameScript::Morale(Scriptable *Sender, const Trigger *parameters)
2456 {
2457 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2458 if (!tar || tar->Type != ST_ACTOR) {
2459 return 0;
2460 }
2461 const Actor *actor = (const Actor *) tar;
2462 bool matched = (signed) actor->GetStat(IE_MORALEBREAK) == parameters->int0Parameter;
2463 if (matched) {
2464 Sender->SetLastTrigger(trigger_morale, actor->GetGlobalID());
2465 }
2466 return matched;
2467 }
2468
MoraleGT(Scriptable * Sender,const Trigger * parameters)2469 int GameScript::MoraleGT(Scriptable *Sender, const Trigger *parameters)
2470 {
2471 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2472 if (!tar || tar->Type != ST_ACTOR) {
2473 return 0;
2474 }
2475 const Actor *actor = (const Actor *) tar;
2476 bool matched = (signed) actor->GetStat(IE_MORALEBREAK) > parameters->int0Parameter;
2477 if (matched) {
2478 Sender->SetLastTrigger(trigger_morale, actor->GetGlobalID());
2479 }
2480 return matched;
2481 }
2482
MoraleLT(Scriptable * Sender,const Trigger * parameters)2483 int GameScript::MoraleLT(Scriptable *Sender, const Trigger *parameters)
2484 {
2485 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2486 if (!tar || tar->Type != ST_ACTOR) {
2487 return 0;
2488 }
2489 const Actor *actor = (const Actor *) tar;
2490 bool matched = (signed) actor->GetStat(IE_MORALEBREAK) < parameters->int0Parameter;
2491 if (matched) {
2492 Sender->SetLastTrigger(trigger_morale, actor->GetGlobalID());
2493 }
2494 return matched;
2495 }
2496
CheckSpellState(Scriptable * Sender,const Trigger * parameters)2497 int GameScript::CheckSpellState(Scriptable *Sender, const Trigger *parameters)
2498 {
2499 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2500 if (!tar || tar->Type != ST_ACTOR) {
2501 return 0;
2502 }
2503 const Actor *actor = (const Actor *) tar;
2504 if (parameters->int0Parameter>255) {
2505 return 0;
2506 }
2507 unsigned int position = parameters->int0Parameter>>5;
2508 unsigned int bit = 1<<(parameters->int0Parameter&31);
2509 if (actor->spellStates[position] & bit) {
2510 return 1;
2511 }
2512 return 0;
2513 }
2514
StateCheck(Scriptable * Sender,const Trigger * parameters)2515 int GameScript::StateCheck(Scriptable *Sender, const Trigger *parameters)
2516 {
2517 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2518 if (!tar || tar->Type != ST_ACTOR) {
2519 return 0;
2520 }
2521 const Actor *actor = (const Actor *) tar;
2522 if (actor->GetStat(IE_STATE_ID) & parameters->int0Parameter) {
2523 Sender->SetLastTrigger(trigger_statecheck, tar->GetGlobalID());
2524 return 1;
2525 }
2526 return 0;
2527 }
2528
ExtendedStateCheck(Scriptable * Sender,const Trigger * parameters)2529 int GameScript::ExtendedStateCheck(Scriptable *Sender, const Trigger *parameters)
2530 {
2531 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2532 if (!tar || tar->Type != ST_ACTOR) {
2533 return 0;
2534 }
2535 const Actor *actor = (const Actor *) tar;
2536 if (actor->GetStat(IE_EXTSTATE_ID) & parameters->int0Parameter) {
2537 return 1;
2538 }
2539 return 0;
2540 }
2541
NotStateCheck(Scriptable * Sender,const Trigger * parameters)2542 int GameScript::NotStateCheck(Scriptable *Sender, const Trigger *parameters)
2543 {
2544 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2545 if (!tar || tar->Type != ST_ACTOR) {
2546 return 0;
2547 }
2548 const Actor *actor = (const Actor *) tar;
2549 if (actor->GetStat(IE_STATE_ID) & ~parameters->int0Parameter) {
2550 Sender->SetLastTrigger(trigger_statecheck, tar->GetGlobalID());
2551 return 1;
2552 }
2553 return 0;
2554 }
2555
RandomNum(Scriptable *,const Trigger * parameters)2556 int GameScript::RandomNum(Scriptable */*Sender*/, const Trigger *parameters)
2557 {
2558 if (parameters->int0Parameter <= 0 || parameters->int1Parameter <= 0) {
2559 return 0;
2560 }
2561 return parameters->int1Parameter-1 == RandomNumValue%parameters->int0Parameter;
2562 }
2563
RandomNumGT(Scriptable *,const Trigger * parameters)2564 int GameScript::RandomNumGT(Scriptable */*Sender*/, const Trigger *parameters)
2565 {
2566 if (parameters->int0Parameter <= 0 || parameters->int1Parameter <= 0) {
2567 return 0;
2568 }
2569 return parameters->int1Parameter-1 < RandomNumValue%parameters->int0Parameter;
2570 }
2571
RandomNumLT(Scriptable *,const Trigger * parameters)2572 int GameScript::RandomNumLT(Scriptable */*Sender*/, const Trigger *parameters)
2573 {
2574 if (parameters->int0Parameter <= 0 || parameters->int1Parameter <= 0) {
2575 return 0;
2576 }
2577 return parameters->int1Parameter-1 > RandomNumValue%parameters->int0Parameter;
2578 }
2579
OpenState(Scriptable * Sender,const Trigger * parameters)2580 int GameScript::OpenState(Scriptable *Sender, const Trigger *parameters)
2581 {
2582 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2583 if (!tar) {
2584 if (core->InDebugMode(ID_TRIGGERS)) {
2585 Log(ERROR, "GameScript", "Couldn't find door/container:%s",
2586 parameters->objectParameter? parameters->objectParameter->objectName:"<NULL>");
2587 print("Sender: %s", Sender->GetScriptName());
2588 }
2589 return 0;
2590 }
2591 switch(tar->Type) {
2592 case ST_DOOR:
2593 {
2594 const Door *door = (const Door *) tar;
2595 return !door->IsOpen() == !parameters->int0Parameter;
2596 }
2597 case ST_CONTAINER:
2598 {
2599 const Container *cont = (const Container *) tar;
2600 return !(cont->Flags&CONT_LOCKED) == !parameters->int0Parameter;
2601 }
2602 default:; //to remove a warning
2603 }
2604 Log(ERROR, "GameScript", "OpenState: Not a door/container: %s", tar->GetScriptName());
2605 return 0;
2606 }
2607
IsLocked(Scriptable * Sender,const Trigger * parameters)2608 int GameScript::IsLocked(Scriptable *Sender, const Trigger *parameters)
2609 {
2610 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2611 if (!tar) {
2612 Log(ERROR, "GameScript", "Couldn't find door/container:%s",
2613 parameters->objectParameter? parameters->objectParameter->objectName:"<NULL>");
2614 print("Sender: %s", Sender->GetScriptName());
2615 return 0;
2616 }
2617 switch(tar->Type) {
2618 case ST_DOOR:
2619 {
2620 const Door *door = (const Door *) tar;
2621 return !!(door->Flags&DOOR_LOCKED);
2622 }
2623 case ST_CONTAINER:
2624 {
2625 const Container *cont = (const Container *) tar;
2626 return !!(cont->Flags&CONT_LOCKED);
2627 }
2628 default:; //to remove a warning
2629 }
2630 Log(ERROR, "GameScript", "IsLocked: Not a door/container: %s", tar->GetScriptName());
2631 return 0;
2632 }
2633
Level(Scriptable * Sender,const Trigger * parameters)2634 int GameScript::Level(Scriptable *Sender, const Trigger *parameters)
2635 {
2636 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2637 if (!tar) {
2638 return 0;
2639 }
2640 if (tar->Type != ST_ACTOR) {
2641 return 0;
2642 }
2643 const Actor *actor = (const Actor *) tar;
2644 // NOTE: which level to check is handled in GetXPLevel. The only user outside of iwd2
2645 // is the bg2 druid grove challenge. Fighter/druid is the only applicable multiclass,
2646 // but the dialog checks for level 14, which both classes reach at the same xp.
2647 // However, checking the gt/lt variants in gorodr1.d (wk start) it becomes clear
2648 // that multiclasses check against their rounded average, like elsewhere:
2649 // f/d levels (8/10: 9 < 10, 8/11: 9.5 >= 10 )
2650 return actor->GetXPLevel(true) == (unsigned) parameters->int0Parameter;
2651 }
2652
2653 // works intuitively only with single-classed characters — the way the originals use it
ClassLevel(Scriptable * Sender,const Trigger * parameters)2654 int GameScript::ClassLevel(Scriptable *Sender, const Trigger *parameters)
2655 {
2656 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2657 if (!tar) {
2658 return 0;
2659 }
2660 if (tar->Type != ST_ACTOR) {
2661 return 0;
2662 }
2663 const Actor *actor = (const Actor *) tar;
2664 return actor->GetLevelInClass(parameters->int0Parameter) == (unsigned) parameters->int1Parameter;
2665 }
2666
2667 // iwd2 and pst have different order of parameters:
2668 // ClassLevelGT(Protagonist,MAGE,10)
2669 // LevelInClass(Myself,10,CLERIC)
LevelInClass(Scriptable * Sender,const Trigger * parameters)2670 int GameScript::LevelInClass(Scriptable *Sender, const Trigger *parameters)
2671 {
2672 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2673 if (!tar) {
2674 return 0;
2675 }
2676 if (tar->Type != ST_ACTOR) {
2677 return 0;
2678 }
2679 const Actor *actor = (const Actor *) tar;
2680 return actor->GetLevelInClass(parameters->int1Parameter) == (unsigned) parameters->int0Parameter;
2681 }
2682
LevelGT(Scriptable * Sender,const Trigger * parameters)2683 int GameScript::LevelGT(Scriptable *Sender, const Trigger *parameters)
2684 {
2685 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2686 if (!tar) {
2687 return 0;
2688 }
2689 if (tar->Type != ST_ACTOR) {
2690 return 0;
2691 }
2692 const Actor *actor = (const Actor *) tar;
2693 return actor->GetXPLevel(true) > (unsigned) parameters->int0Parameter;
2694 }
2695
ClassLevelGT(Scriptable * Sender,const Trigger * parameters)2696 int GameScript::ClassLevelGT(Scriptable *Sender, const Trigger *parameters)
2697 {
2698 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2699 if (!tar) {
2700 return 0;
2701 }
2702 if (tar->Type != ST_ACTOR) {
2703 return 0;
2704 }
2705 const Actor *actor = (const Actor *) tar;
2706 return actor->GetLevelInClass(parameters->int0Parameter) > (unsigned) parameters->int1Parameter;
2707 }
2708
LevelInClassGT(Scriptable * Sender,const Trigger * parameters)2709 int GameScript::LevelInClassGT(Scriptable *Sender, const Trigger *parameters)
2710 {
2711 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2712 if (!tar) {
2713 return 0;
2714 }
2715 if (tar->Type != ST_ACTOR) {
2716 return 0;
2717 }
2718 const Actor *actor = (const Actor *) tar;
2719 return actor->GetLevelInClass(parameters->int1Parameter) > (unsigned) parameters->int0Parameter;
2720 }
2721
LevelLT(Scriptable * Sender,const Trigger * parameters)2722 int GameScript::LevelLT(Scriptable *Sender, const Trigger *parameters)
2723 {
2724 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2725 if (!tar) {
2726 return 0;
2727 }
2728 if (tar->Type != ST_ACTOR) {
2729 return 0;
2730 }
2731 const Actor *actor = (const Actor *) tar;
2732 return actor->GetXPLevel(true) < (unsigned) parameters->int0Parameter;
2733 }
2734
ClassLevelLT(Scriptable * Sender,const Trigger * parameters)2735 int GameScript::ClassLevelLT(Scriptable *Sender, const Trigger *parameters)
2736 {
2737 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2738 if (!tar) {
2739 return 0;
2740 }
2741 if (tar->Type != ST_ACTOR) {
2742 return 0;
2743 }
2744 const Actor *actor = (const Actor *) tar;
2745 return actor->GetLevelInClass(parameters->int0Parameter) < (unsigned) parameters->int1Parameter;
2746 }
2747
LevelInClassLT(Scriptable * Sender,const Trigger * parameters)2748 int GameScript::LevelInClassLT(Scriptable *Sender, const Trigger *parameters)
2749 {
2750 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2751 if (!tar) {
2752 return 0;
2753 }
2754 if (tar->Type != ST_ACTOR) {
2755 return 0;
2756 }
2757 const Actor *actor = (const Actor *) tar;
2758 return actor->GetLevelInClass(parameters->int1Parameter) < (unsigned) parameters->int0Parameter;
2759 }
2760
UnselectableVariable(Scriptable * Sender,const Trigger * parameters)2761 int GameScript::UnselectableVariable(Scriptable *Sender, const Trigger *parameters)
2762 {
2763 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2764 if (!tar) {
2765 return 0;
2766 }
2767 return tar->UnselectableTimer == (unsigned) parameters->int0Parameter;
2768 }
2769
UnselectableVariableGT(Scriptable * Sender,const Trigger * parameters)2770 int GameScript::UnselectableVariableGT(Scriptable *Sender, const Trigger *parameters)
2771 {
2772 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2773 if (!tar) {
2774 return 0;
2775 }
2776 return tar->UnselectableTimer > (unsigned) parameters->int0Parameter;
2777 }
2778
UnselectableVariableLT(Scriptable * Sender,const Trigger * parameters)2779 int GameScript::UnselectableVariableLT(Scriptable *Sender, const Trigger *parameters)
2780 {
2781 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2782 if (!tar) {
2783 return 0;
2784 }
2785 return tar->UnselectableTimer < (unsigned) parameters->int0Parameter;
2786 }
2787
AreaCheck(Scriptable * Sender,const Trigger * parameters)2788 int GameScript::AreaCheck(Scriptable *Sender, const Trigger *parameters)
2789 {
2790 const Map *area = Sender->GetCurrentArea();
2791 if (!area) return 0;
2792
2793 if (!strnicmp(area->GetScriptName(), parameters->string0Parameter, 8)) {
2794 return 1;
2795 }
2796 return 0;
2797 }
2798
AreaCheckObject(Scriptable * Sender,const Trigger * parameters)2799 int GameScript::AreaCheckObject(Scriptable *Sender, const Trigger *parameters)
2800 {
2801 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2802
2803 if (!tar) {
2804 return 0;
2805 }
2806 const Map *map = tar->GetCurrentArea();
2807 if (!map) {
2808 return 0;
2809 }
2810 if (!strnicmp(map->GetScriptName(), parameters->string0Parameter, 8)) {
2811 return 1;
2812 }
2813 return 0;
2814 }
2815
2816 //lame iwd2 uses a numeric area identifier, this reduces its usability
CurrentAreaIs(Scriptable * Sender,const Trigger * parameters)2817 int GameScript::CurrentAreaIs(Scriptable *Sender, const Trigger *parameters)
2818 {
2819 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2820
2821 if (!tar) {
2822 return 0;
2823 }
2824 ieResRef arearesref;
2825 snprintf(arearesref, 8, "AR%04d", parameters->int0Parameter);
2826 if (!strnicmp(tar->GetCurrentArea()->GetScriptName(), arearesref, 8)) {
2827 return 1;
2828 }
2829 return 0;
2830 }
2831
2832 //lame bg2 uses a constant areaname prefix, this reduces its usability
2833 //but in the spirit of flexibility, gemrb extension allows arbitrary prefixes
AreaStartsWith(Scriptable * Sender,const Trigger * parameters)2834 int GameScript::AreaStartsWith(Scriptable *Sender, const Trigger *parameters)
2835 {
2836 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2837
2838 if (!tar) {
2839 return 0;
2840 }
2841 ieResRef arearesref;
2842 if (parameters->string0Parameter[0]) {
2843 strnlwrcpy(arearesref, parameters->string0Parameter, 8);
2844 } else {
2845 strnlwrcpy(arearesref, "AR30", 8); //InWatchersKeep
2846 }
2847 size_t i = strlen(arearesref);
2848 if (!strnicmp(tar->GetCurrentArea()->GetScriptName(), arearesref, i)) {
2849 return 1;
2850 }
2851 return 0;
2852 }
2853
EntirePartyOnMap(Scriptable * Sender,const Trigger *)2854 int GameScript::EntirePartyOnMap(Scriptable *Sender, const Trigger */*parameters*/)
2855 {
2856 Map *map = Sender->GetCurrentArea();
2857 const Game *game = core->GetGame();
2858 int i=game->GetPartySize(true);
2859 while (i--) {
2860 const Actor *actor = game->GetPC(i, true);
2861 if (actor->GetCurrentArea() != map) {
2862 return 0;
2863 }
2864 }
2865 return 1;
2866 }
2867
AnyPCOnMap(Scriptable * Sender,const Trigger *)2868 int GameScript::AnyPCOnMap(Scriptable *Sender, const Trigger */*parameters*/)
2869 {
2870 Map *map = Sender->GetCurrentArea();
2871 const Game *game = core->GetGame();
2872 int i=game->GetPartySize(true);
2873 while (i--) {
2874 const Actor *actor = game->GetPC(i,true);
2875 if (actor->GetCurrentArea() == map) {
2876 return 1;
2877 }
2878 }
2879 return 0;
2880 }
2881
InActiveArea(Scriptable * Sender,const Trigger * parameters)2882 int GameScript::InActiveArea(Scriptable *Sender, const Trigger *parameters)
2883 {
2884 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2885 if (!tar) {
2886 return 0;
2887 }
2888 if (core->GetGame()->GetCurrentArea() == tar->GetCurrentArea()) {
2889 return 1;
2890 }
2891 return 0;
2892 }
2893
InMyArea(Scriptable * Sender,const Trigger * parameters)2894 int GameScript::InMyArea(Scriptable *Sender, const Trigger *parameters)
2895 {
2896 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
2897 if (!tar) {
2898 return 0;
2899 }
2900 if (Sender->GetCurrentArea() == tar->GetCurrentArea()) {
2901 return 1;
2902 }
2903 return 0;
2904 }
2905
AreaType(Scriptable * Sender,const Trigger * parameters)2906 int GameScript::AreaType(Scriptable *Sender, const Trigger *parameters)
2907 {
2908 const Map *map = Sender->GetCurrentArea();
2909 if (!map) {
2910 return 1;
2911 }
2912 return (map->AreaType¶meters->int0Parameter)>0;
2913 }
2914
IsExtendedNight(Scriptable * Sender,const Trigger *)2915 int GameScript::IsExtendedNight( Scriptable *Sender, const Trigger */*parameters*/)
2916 {
2917 const Map *map = Sender->GetCurrentArea();
2918 if (!map) {
2919 return 1;
2920 }
2921 if (map->AreaType&AT_EXTENDED_NIGHT) {
2922 return 1;
2923 }
2924 return 0;
2925 }
2926
AreaFlag(Scriptable * Sender,const Trigger * parameters)2927 int GameScript::AreaFlag(Scriptable *Sender, const Trigger *parameters)
2928 {
2929 const Map *map = Sender->GetCurrentArea();
2930 if (!map) {
2931 return 1;
2932 }
2933 return (map->AreaFlags¶meters->int0Parameter)>0;
2934 }
2935
AreaRestDisabled(Scriptable * Sender,const Trigger *)2936 int GameScript::AreaRestDisabled(Scriptable *Sender, const Trigger */*parameters*/)
2937 {
2938 const Map *map = Sender->GetCurrentArea();
2939 if (!map) {
2940 return 1;
2941 }
2942 if (map->AreaFlags&2) {
2943 return 1;
2944 }
2945 return 0;
2946 }
2947
TargetUnreachable(Scriptable * Sender,const Trigger *)2948 int GameScript::TargetUnreachable(Scriptable *Sender, const Trigger */*parameters*/)
2949 {
2950 return Sender->MatchTrigger(trigger_targetunreachable);
2951 }
2952
PartyCountEQ(Scriptable *,const Trigger * parameters)2953 int GameScript::PartyCountEQ(Scriptable */*Sender*/, const Trigger *parameters)
2954 {
2955 return core->GetGame()->GetPartySize(false) == parameters->int0Parameter;
2956 }
2957
PartyCountLT(Scriptable *,const Trigger * parameters)2958 int GameScript::PartyCountLT(Scriptable */*Sender*/, const Trigger *parameters)
2959 {
2960 return core->GetGame()->GetPartySize(false) < parameters->int0Parameter;
2961 }
2962
PartyCountGT(Scriptable *,const Trigger * parameters)2963 int GameScript::PartyCountGT(Scriptable */*Sender*/, const Trigger *parameters)
2964 {
2965 return core->GetGame()->GetPartySize(false) > parameters->int0Parameter;
2966 }
2967
PartyCountAliveEQ(Scriptable *,const Trigger * parameters)2968 int GameScript::PartyCountAliveEQ(Scriptable */*Sender*/, const Trigger *parameters)
2969 {
2970 return core->GetGame()->GetPartySize(true) == parameters->int0Parameter;
2971 }
2972
PartyCountAliveLT(Scriptable *,const Trigger * parameters)2973 int GameScript::PartyCountAliveLT(Scriptable */*Sender*/, const Trigger *parameters)
2974 {
2975 return core->GetGame()->GetPartySize(true) < parameters->int0Parameter;
2976 }
2977
PartyCountAliveGT(Scriptable *,const Trigger * parameters)2978 int GameScript::PartyCountAliveGT(Scriptable */*Sender*/, const Trigger *parameters)
2979 {
2980 return core->GetGame()->GetPartySize(true) > parameters->int0Parameter;
2981 }
2982
LevelParty(Scriptable *,const Trigger * parameters)2983 int GameScript::LevelParty(Scriptable */*Sender*/, const Trigger *parameters)
2984 {
2985 int count = core->GetGame()->GetPartySize(true);
2986
2987 if (count) {
2988 return core->GetGame()->GetTotalPartyLevel(true) / count == parameters->int0Parameter;
2989 }
2990 return 0;
2991 }
2992
LevelPartyLT(Scriptable *,const Trigger * parameters)2993 int GameScript::LevelPartyLT(Scriptable */*Sender*/, const Trigger *parameters)
2994 {
2995 int count = core->GetGame()->GetPartySize(true);
2996
2997 if (count) {
2998 return core->GetGame()->GetTotalPartyLevel(true) / count < parameters->int0Parameter;
2999 }
3000 return 0;
3001 }
3002
LevelPartyGT(Scriptable *,const Trigger * parameters)3003 int GameScript::LevelPartyGT(Scriptable */*Sender*/, const Trigger *parameters)
3004 {
3005 int count = core->GetGame()->GetPartySize(true);
3006
3007 if (count) {
3008 return core->GetGame()->GetTotalPartyLevel(true) / count > parameters->int0Parameter;
3009 }
3010 return 0;
3011 }
3012
PartyGold(Scriptable *,const Trigger * parameters)3013 int GameScript::PartyGold(Scriptable */*Sender*/, const Trigger *parameters)
3014 {
3015 return core->GetGame()->PartyGold == (ieDword) parameters->int0Parameter;
3016 }
3017
PartyGoldGT(Scriptable *,const Trigger * parameters)3018 int GameScript::PartyGoldGT(Scriptable */*Sender*/, const Trigger *parameters)
3019 {
3020 return core->GetGame()->PartyGold > (ieDword) parameters->int0Parameter;
3021 }
3022
PartyGoldLT(Scriptable *,const Trigger * parameters)3023 int GameScript::PartyGoldLT(Scriptable */*Sender*/, const Trigger *parameters)
3024 {
3025 return core->GetGame()->PartyGold < (ieDword) parameters->int0Parameter;
3026 }
3027
OwnsFloaterMessage(Scriptable * Sender,const Trigger * parameters)3028 int GameScript::OwnsFloaterMessage(Scriptable *Sender, const Trigger *parameters)
3029 {
3030 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3031 if (!tar) {
3032 return 0;
3033 }
3034 return tar->OverheadTextIsDisplaying();
3035 }
3036
InCutSceneMode(Scriptable *,const Trigger *)3037 int GameScript::InCutSceneMode(Scriptable */*Sender*/, const Trigger */*parameters*/)
3038 {
3039 return core->InCutSceneMode();
3040 }
3041
Proficiency(Scriptable * Sender,const Trigger * parameters)3042 int GameScript::Proficiency(Scriptable *Sender, const Trigger *parameters)
3043 {
3044 unsigned int idx = parameters->int0Parameter;
3045 if (idx>31) {
3046 return 0;
3047 }
3048 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3049 if (!tar) {
3050 return 0;
3051 }
3052 if (tar->Type != ST_ACTOR) {
3053 return 0;
3054 }
3055 const Actor *actor = (const Actor *) tar;
3056 return (signed) actor->GetStat(IE_PROFICIENCYBASTARDSWORD+idx) == parameters->int1Parameter;
3057 }
3058
ProficiencyGT(Scriptable * Sender,const Trigger * parameters)3059 int GameScript::ProficiencyGT(Scriptable *Sender, const Trigger *parameters)
3060 {
3061 unsigned int idx = parameters->int0Parameter;
3062 if (idx>31) {
3063 return 0;
3064 }
3065 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3066 if (!tar) {
3067 return 0;
3068 }
3069 if (tar->Type != ST_ACTOR) {
3070 return 0;
3071 }
3072 const Actor *actor = (const Actor *) tar;
3073 return (signed) actor->GetStat(IE_PROFICIENCYBASTARDSWORD+idx) > parameters->int1Parameter;
3074 }
3075
ProficiencyLT(Scriptable * Sender,const Trigger * parameters)3076 int GameScript::ProficiencyLT(Scriptable *Sender, const Trigger *parameters)
3077 {
3078 unsigned int idx = parameters->int0Parameter;
3079 if (idx>31) {
3080 return 0;
3081 }
3082 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3083 if (!tar) {
3084 return 0;
3085 }
3086 if (tar->Type != ST_ACTOR) {
3087 return 0;
3088 }
3089 const Actor *actor = (const Actor *) tar;
3090 return (signed) actor->GetStat(IE_PROFICIENCYBASTARDSWORD+idx) < parameters->int1Parameter;
3091 }
3092
3093 //this is a PST specific stat, shows how many free proficiency slots we got
3094 //we use an unused stat for it
ExtraProficiency(Scriptable * Sender,const Trigger * parameters)3095 int GameScript::ExtraProficiency(Scriptable *Sender, const Trigger *parameters)
3096 {
3097 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3098 if (!tar) {
3099 return 0;
3100 }
3101 if (tar->Type != ST_ACTOR) {
3102 return 0;
3103 }
3104 const Actor *actor = (const Actor *) tar;
3105 return (signed) actor->GetStat(IE_FREESLOTS) == parameters->int0Parameter;
3106 }
3107
ExtraProficiencyGT(Scriptable * Sender,const Trigger * parameters)3108 int GameScript::ExtraProficiencyGT(Scriptable *Sender, const Trigger *parameters)
3109 {
3110 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3111 if (!tar) {
3112 return 0;
3113 }
3114 if (tar->Type != ST_ACTOR) {
3115 return 0;
3116 }
3117 const Actor *actor = (const Actor *) tar;
3118 return (signed) actor->GetStat(IE_FREESLOTS) > parameters->int0Parameter;
3119 }
3120
ExtraProficiencyLT(Scriptable * Sender,const Trigger * parameters)3121 int GameScript::ExtraProficiencyLT(Scriptable *Sender, const Trigger *parameters)
3122 {
3123 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3124 if (!tar) {
3125 return 0;
3126 }
3127 if (tar->Type != ST_ACTOR) {
3128 return 0;
3129 }
3130 const Actor *actor = (const Actor *) tar;
3131 return (signed) actor->GetStat(IE_FREESLOTS) < parameters->int0Parameter;
3132 }
3133
Internal(Scriptable * Sender,const Trigger * parameters)3134 int GameScript::Internal(Scriptable *Sender, const Trigger *parameters)
3135 {
3136 unsigned int idx = parameters->int0Parameter;
3137 if (idx>15) {
3138 return 0;
3139 }
3140 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3141 if (!tar) {
3142 return 0;
3143 }
3144 if (tar->Type != ST_ACTOR) {
3145 return 0;
3146 }
3147 const Actor *actor = (const Actor *) tar;
3148 return (signed) actor->GetStat(IE_INTERNAL_0+idx) == parameters->int1Parameter;
3149 }
3150
InternalGT(Scriptable * Sender,const Trigger * parameters)3151 int GameScript::InternalGT(Scriptable *Sender, const Trigger *parameters)
3152 {
3153 unsigned int idx = parameters->int0Parameter;
3154 if (idx>15) {
3155 return 0;
3156 }
3157 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3158 if (!tar) {
3159 return 0;
3160 }
3161 if (tar->Type != ST_ACTOR) {
3162 return 0;
3163 }
3164 const Actor *actor = (const Actor *) tar;
3165 return (signed) actor->GetStat(IE_INTERNAL_0+idx) > parameters->int1Parameter;
3166 }
3167
InternalLT(Scriptable * Sender,const Trigger * parameters)3168 int GameScript::InternalLT(Scriptable *Sender, const Trigger *parameters)
3169 {
3170 unsigned int idx = parameters->int0Parameter;
3171 if (idx>15) {
3172 return 0;
3173 }
3174 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3175 if (!tar) {
3176 return 0;
3177 }
3178 if (tar->Type != ST_ACTOR) {
3179 return 0;
3180 }
3181 const Actor *actor = (const Actor *) tar;
3182 return (signed) actor->GetStat(IE_INTERNAL_0+idx) < parameters->int1Parameter;
3183 }
3184
3185 //we check if target is currently in dialog or not
NullDialog(Scriptable * Sender,const Trigger * parameters)3186 int GameScript::NullDialog(Scriptable *Sender, const Trigger *parameters)
3187 {
3188 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3189 if (!tar) {
3190 return 0;
3191 }
3192 if (tar->Type != ST_ACTOR) {
3193 return 0;
3194 }
3195 const GameControl *gc = core->GetGameControl();
3196 if (!gc->dialoghandler->InDialog(tar)) {
3197 return 1;
3198 }
3199 return 0;
3200 }
3201
3202 //this one checks scriptname (deathvar), i hope it is right
3203 //IsScriptName depends on this too
3204 //Name is another (similar function)
CalledByName(Scriptable * Sender,const Trigger * parameters)3205 int GameScript::CalledByName(Scriptable *Sender, const Trigger *parameters)
3206 {
3207 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3208 if (!tar) {
3209 return 0;
3210 }
3211 if (tar->Type != ST_ACTOR) {
3212 return 0;
3213 }
3214 const Actor *actor = (const Actor *) tar;
3215 if (stricmp(actor->GetScriptName(), parameters->string0Parameter) ) {
3216 return 0;
3217 }
3218 return 1;
3219 }
3220
3221 //This is checking on the character's name as it was typed in
CharName(Scriptable * Sender,const Trigger * parameters)3222 int GameScript::CharName(Scriptable *Sender, const Trigger *parameters)
3223 {
3224 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
3225 if (!scr || scr->Type!=ST_ACTOR) {
3226 return 0;
3227 }
3228 const Actor *actor = (const Actor *) scr;
3229 if (!strnicmp(actor->ShortName, parameters->string0Parameter, 32) ) {
3230 return 1;
3231 }
3232 return 0;
3233 }
3234
AnimationID(Scriptable * Sender,const Trigger * parameters)3235 int GameScript::AnimationID(Scriptable *Sender, const Trigger *parameters)
3236 {
3237 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3238 if (!tar) {
3239 return 0;
3240 }
3241 if (tar->Type != ST_ACTOR) {
3242 return 0;
3243 }
3244 const Actor *actor = (const Actor *) tar;
3245 if ((ieWord) actor->GetStat(IE_ANIMATION_ID) == (ieWord) parameters->int0Parameter) {
3246 return 1;
3247 }
3248 return 0;
3249 }
3250
AnimState(Scriptable * Sender,const Trigger * parameters)3251 int GameScript::AnimState(Scriptable *Sender, const Trigger *parameters)
3252 {
3253 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3254 if (!tar) {
3255 return 0;
3256 }
3257 if (tar->Type != ST_ACTOR) {
3258 return 0;
3259 }
3260 const Actor *actor = (const Actor *) tar;
3261 return actor->GetStance() == parameters->int0Parameter;
3262 }
3263
3264 //this trigger uses hours
Time(Scriptable *,const Trigger * parameters)3265 int GameScript::Time(Scriptable */*Sender*/, const Trigger *parameters)
3266 {
3267 int hour = parameters->int0Parameter;
3268 if (hour < 0 || hour > 23) return 0;
3269
3270 if (!hour) hour = 24;
3271 return Schedule(1 << (hour - 1), core->GetGame()->GameTime);
3272 }
3273
3274 //this trigger uses hours
TimeGT(Scriptable *,const Trigger * parameters)3275 int GameScript::TimeGT(Scriptable */*Sender*/, const Trigger *parameters)
3276 {
3277 if (parameters->int0Parameter < 0 || parameters->int0Parameter > 22) return 0;
3278
3279 return Schedule((0xFFFFFFu << parameters->int0Parameter) & 0x7FFFFFu, core->GetGame()->GameTime);
3280 }
3281
3282 //this trigger uses hours
TimeLT(Scriptable *,const Trigger * parameters)3283 int GameScript::TimeLT(Scriptable */*Sender*/, const Trigger *parameters)
3284 {
3285 if (parameters->int0Parameter < 1 || parameters->int0Parameter > 23) return 0;
3286
3287 return Schedule((0xFFFFFFu >> (25 - parameters->int0Parameter)) | 1 << 23, core->GetGame()->GameTime);
3288 }
3289
HotKey(Scriptable * Sender,const Trigger * parameters)3290 int GameScript::HotKey(Scriptable *Sender, const Trigger *parameters)
3291 {
3292 return Sender->MatchTrigger(trigger_hotkey, parameters->int0Parameter);
3293 }
3294
CombatCounter(Scriptable *,const Trigger * parameters)3295 int GameScript::CombatCounter(Scriptable */*Sender*/, const Trigger *parameters)
3296 {
3297 return core->GetGame()->CombatCounter == (ieDword) parameters->int0Parameter;
3298 }
3299
CombatCounterGT(Scriptable *,const Trigger * parameters)3300 int GameScript::CombatCounterGT(Scriptable */*Sender*/, const Trigger *parameters)
3301 {
3302 return core->GetGame()->CombatCounter > (ieDword) parameters->int0Parameter;
3303 }
3304
CombatCounterLT(Scriptable *,const Trigger * parameters)3305 int GameScript::CombatCounterLT(Scriptable */*Sender*/, const Trigger *parameters)
3306 {
3307 return core->GetGame()->CombatCounter < (ieDword) parameters->int0Parameter;
3308 }
3309
TrapTriggered(Scriptable * Sender,const Trigger * parameters)3310 int GameScript::TrapTriggered(Scriptable *Sender, const Trigger *parameters)
3311 {
3312 return Sender->MatchTriggerWithObject(trigger_traptriggered, parameters->objectParameter);
3313 }
3314
InteractingWith(Scriptable * Sender,const Trigger * parameters)3315 int GameScript::InteractingWith(Scriptable *Sender, const Trigger *parameters)
3316 {
3317 if (Sender->Type!=ST_ACTOR) {
3318 return 0;
3319 }
3320 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3321 if (!tar || tar->Type != ST_ACTOR) {
3322 return 0;
3323 }
3324 const GameControl *gc = core->GetGameControl();
3325 if (!gc->dialoghandler->InDialog(Sender)) {
3326 return 0;
3327 }
3328 if (!gc->dialoghandler->InDialog(tar)) {
3329 return 0;
3330 }
3331 return 1;
3332 }
3333
LastPersonTalkedTo(Scriptable * Sender,const Trigger * parameters)3334 int GameScript::LastPersonTalkedTo(Scriptable *Sender, const Trigger *parameters)
3335 {
3336 if (Sender->Type!=ST_ACTOR) {
3337 return 0;
3338 }
3339 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3340 if (!tar || tar->Type != ST_ACTOR) {
3341 return 0;
3342 }
3343 const Actor *scr = (const Actor *) Sender;
3344 if (MatchActor(Sender, scr->LastTalker, parameters->objectParameter)) {
3345 return 1;
3346 }
3347 return 0;
3348 }
3349
IsRotation(Scriptable * Sender,const Trigger * parameters)3350 int GameScript::IsRotation(Scriptable *Sender, const Trigger *parameters)
3351 {
3352 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3353 if (!tar || tar->Type != ST_ACTOR) {
3354 return 0;
3355 }
3356 const Actor *actor = (const Actor *) tar;
3357 if ( actor->GetOrientation() == parameters->int0Parameter ) {
3358 return 1;
3359 }
3360 return 0;
3361 }
3362
3363 //GemRB currently stores the saved location in a local variable, but it is
3364 //actually stored in the .gam structure (only for PCs)
IsFacingSavedRotation(Scriptable * Sender,const Trigger * parameters)3365 int GameScript::IsFacingSavedRotation(Scriptable *Sender, const Trigger *parameters)
3366 {
3367 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3368 if (!tar || tar->Type!=ST_ACTOR) {
3369 return 0;
3370 }
3371 const Actor *actor = (const Actor *) tar;
3372 if (actor->GetOrientation() == actor->GetStat(IE_SAVEDFACE) ) {
3373 return 1;
3374 }
3375 return 0;
3376 }
3377
IsFacingObject(Scriptable * Sender,const Trigger * parameters)3378 int GameScript::IsFacingObject(Scriptable *Sender, const Trigger *parameters)
3379 {
3380 if (Sender->Type != ST_ACTOR) {
3381 return 0;
3382 }
3383 const Scriptable *target = GetActorFromObject(Sender, parameters->objectParameter);
3384 if (!target) {
3385 return 0;
3386 }
3387 const Actor *actor = (const Actor *) Sender;
3388 if (actor->GetOrientation() == GetOrient(target->Pos, actor->Pos)) {
3389 return 1;
3390 }
3391 return 0;
3392 }
3393
AttackedBy(Scriptable * Sender,const Trigger * parameters)3394 int GameScript::AttackedBy(Scriptable *Sender, const Trigger *parameters)
3395 {
3396 bool match = Sender->MatchTriggerWithObject(trigger_attackedby, parameters->objectParameter, parameters->int0Parameter);
3397 const Scriptable *target = GetActorFromObject(Sender, parameters->objectParameter);
3398 if (match && target && Sender->Type == ST_ACTOR) {
3399 Sender->LastMarked = target->GetGlobalID();
3400 }
3401 return match;
3402 }
3403
TookDamage(Scriptable * Sender,const Trigger *)3404 int GameScript::TookDamage(Scriptable *Sender, const Trigger */*parameters*/)
3405 {
3406 return Sender->MatchTrigger(trigger_tookdamage);
3407 }
3408
HitBy(Scriptable * Sender,const Trigger * parameters)3409 int GameScript::HitBy(Scriptable *Sender, const Trigger *parameters)
3410 {
3411 return Sender->MatchTriggerWithObject(trigger_hitby, parameters->objectParameter, parameters->int0Parameter);
3412 }
3413
Heard(Scriptable * Sender,const Trigger * parameters)3414 int GameScript::Heard(Scriptable *Sender, const Trigger *parameters)
3415 {
3416 return Sender->MatchTriggerWithObject(trigger_heard, parameters->objectParameter, parameters->int0Parameter);
3417 }
3418
Detected(Scriptable * Sender,const Trigger * parameters)3419 int GameScript::Detected(Scriptable *Sender, const Trigger *parameters)
3420 {
3421 return Sender->MatchTriggerWithObject(trigger_detected, parameters->objectParameter, parameters->int0Parameter);
3422 }
3423
LastMarkedObject_Trigger(Scriptable * Sender,const Trigger * parameters)3424 int GameScript::LastMarkedObject_Trigger(Scriptable *Sender, const Trigger *parameters)
3425 {
3426 if (Sender->Type!=ST_ACTOR) {
3427 return 0;
3428 }
3429 const Actor *actor = (const Actor *) Sender;
3430 if (MatchActor(Sender, actor->LastMarked, parameters->objectParameter)) {
3431 //don't mark this object for clear
3432 //Sender->AddTrigger(&actor->LastSeen);
3433 return 1;
3434 }
3435 return 0;
3436 }
3437
HelpEX(Scriptable * Sender,const Trigger * parameters)3438 int GameScript::HelpEX(Scriptable *Sender, const Trigger *parameters)
3439 {
3440 if (Sender->Type!=ST_ACTOR) {
3441 return 0;
3442 }
3443 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3444 if (!tar || tar->Type!=ST_ACTOR) {
3445 //a non actor checking for help?
3446 return 0;
3447 }
3448 const Actor *actor = (const Actor *) tar;
3449 const Actor *help = Sender->GetCurrentArea()->GetActorByGlobalID(actor->LastHelp);
3450 if (!help) {
3451 //no help required
3452 return 0;
3453 }
3454
3455 int stat;
3456 switch (parameters->int0Parameter) {
3457 case 1: stat = IE_EA; break;
3458 case 2: stat = IE_GENERAL; break;
3459 case 3: stat = IE_RACE; break;
3460 case 4: stat = IE_CLASS; break;
3461 case 5: stat = IE_SPECIFIC; break;
3462 case 6: stat = IE_SEX; break;
3463 case 7: stat = IE_ALIGNMENT; break;
3464 default: return 0;
3465 }
3466 bool match = false;
3467 if (stat == IE_CLASS) {
3468 match = actor->GetActiveClass() == help->GetActiveClass();
3469 } else if (actor->GetStat(stat) == help->GetStat(stat)) {
3470 // FIXME
3471 //Sender->AddTrigger(&actor->LastHelp);
3472 match = true;
3473 }
3474 if (match && Sender->Type == ST_ACTOR) {
3475 Sender->LastMarked = actor->GetGlobalID();
3476 }
3477 return match;
3478 }
3479
Help_Trigger(Scriptable * Sender,const Trigger * parameters)3480 int GameScript::Help_Trigger(Scriptable *Sender, const Trigger *parameters)
3481 {
3482 bool match = Sender->MatchTriggerWithObject(trigger_help, parameters->objectParameter);
3483 const Scriptable *target = GetActorFromObject(Sender, parameters->objectParameter);
3484 if (match && target && Sender->Type == ST_ACTOR) {
3485 Sender->LastMarked = target->GetGlobalID();
3486 }
3487 return match;
3488 }
3489
3490 // a few values are named in order.ids
ReceivedOrder(Scriptable * Sender,const Trigger * parameters)3491 int GameScript::ReceivedOrder(Scriptable *Sender, const Trigger *parameters)
3492 {
3493 return Sender->MatchTriggerWithObject(trigger_receivedorder, parameters->objectParameter, parameters->int0Parameter);
3494 }
3495
Joins(Scriptable * Sender,const Trigger * parameters)3496 int GameScript::Joins(Scriptable *Sender, const Trigger *parameters)
3497 {
3498 return Sender->MatchTriggerWithObject(trigger_joins, parameters->objectParameter);
3499 }
3500
Leaves(Scriptable * Sender,const Trigger * parameters)3501 int GameScript::Leaves(Scriptable *Sender, const Trigger *parameters)
3502 {
3503 return Sender->MatchTriggerWithObject(trigger_leaves, parameters->objectParameter);
3504 }
3505
FallenPaladin(Scriptable * Sender,const Trigger *)3506 int GameScript::FallenPaladin(Scriptable *Sender, const Trigger */*parameters*/)
3507 {
3508 if (Sender->Type!=ST_ACTOR) {
3509 return 0;
3510 }
3511 const Actor *act = (const Actor *) Sender;
3512 return (act->GetStat(IE_MC_FLAGS) & MC_FALLEN_PALADIN) != 0;
3513 }
3514
FallenRanger(Scriptable * Sender,const Trigger *)3515 int GameScript::FallenRanger(Scriptable *Sender, const Trigger */*parameters*/)
3516 {
3517 if (Sender->Type!=ST_ACTOR) {
3518 return 0;
3519 }
3520 const Actor *act = (const Actor *) Sender;
3521 return (act->GetStat(IE_MC_FLAGS) & MC_FALLEN_RANGER) != 0;
3522 }
3523
NightmareModeOn(Scriptable *,const Trigger *)3524 int GameScript::NightmareModeOn(Scriptable */*Sender*/, const Trigger */*parameters*/)
3525 {
3526 ieDword diff = 0;
3527 const Game *game = core->GetGame();
3528
3529 if (game->version == 11) { // GAM_VER_IWD
3530 core->GetDictionary()->Lookup("Nightmare Mode", diff);
3531 } else if (game->version == 22) { // GAM_VER_IWD2
3532 diff = game->HOFMode;
3533 }
3534
3535 if (diff) {
3536 return 1;
3537 }
3538 return 0;
3539 }
3540
StoryModeOn(Scriptable *,const Trigger *)3541 int GameScript::StoryModeOn(Scriptable */*Sender*/, const Trigger */*parameters*/)
3542 {
3543 ieDword mode;
3544
3545 core->GetDictionary()->Lookup("Story Mode", mode);
3546 if (mode) {
3547 return 1;
3548 }
3549 return 0;
3550 }
3551
3552 // the original was more complicated, but we simplify by doing more work in AREImporter
CheckAreaDiffLevel(Scriptable *,const Trigger * parameters)3553 int GameScript::CheckAreaDiffLevel(Scriptable */*Sender*/, const Trigger *parameters)
3554 {
3555 const Map *map = core->GetGame()->GetCurrentArea();
3556 if (!map) return 0;
3557 return map->AreaDifficulty == 1 << (parameters->int0Parameter - 1);
3558 }
3559
Difficulty(Scriptable *,const Trigger * parameters)3560 int GameScript::Difficulty(Scriptable */*Sender*/, const Trigger *parameters)
3561 {
3562 ieDword diff;
3563
3564 core->GetDictionary()->Lookup("Difficulty Level", diff);
3565 int mode = parameters->int1Parameter;
3566 //hack for compatibility
3567 if (!mode) {
3568 mode = EQUALS;
3569 }
3570 return DiffCore(diff+1, (ieDword) parameters->int0Parameter, mode);
3571 }
3572
DifficultyGT(Scriptable *,const Trigger * parameters)3573 int GameScript::DifficultyGT(Scriptable */*Sender*/, const Trigger *parameters)
3574 {
3575 ieDword diff;
3576
3577 core->GetDictionary()->Lookup("Difficulty Level", diff);
3578 return diff+1>(ieDword) parameters->int0Parameter;
3579 }
3580
DifficultyLT(Scriptable *,const Trigger * parameters)3581 int GameScript::DifficultyLT(Scriptable */*Sender*/, const Trigger *parameters)
3582 {
3583 ieDword diff;
3584
3585 core->GetDictionary()->Lookup("Difficulty Level", diff);
3586 return diff+1<(ieDword) parameters->int0Parameter;
3587 }
3588
Vacant(Scriptable * Sender,const Trigger *)3589 int GameScript::Vacant(Scriptable *Sender, const Trigger */*parameters*/)
3590 {
3591 if (Sender->Type!=ST_AREA) {
3592 return 0;
3593 }
3594 const Map *map = (Map *) Sender;
3595 // map->CanFree() has side effects, don't use it here! Would make some loot and corpses disappear immediately
3596 int i = map->GetActorCount(true);
3597 while (i--) {
3598 const Actor *actor = map->GetActor(i, true);
3599 bool usedExit = actor->GetInternalFlag() & IF_USEEXIT;
3600 if (actor->IsPartyMember()) {
3601 if (!usedExit) {
3602 return 0;
3603 }
3604 } else if (usedExit) {
3605 return 0;
3606 }
3607 }
3608 return 1;
3609 }
3610
3611 //this trigger always checks the right hand weapon?
InWeaponRange(Scriptable * Sender,const Trigger * parameters)3612 int GameScript::InWeaponRange(Scriptable *Sender, const Trigger *parameters)
3613 {
3614 if (Sender->Type!=ST_ACTOR) {
3615 return 0;
3616 }
3617 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3618 if (!tar) {
3619 return 0;
3620 }
3621 const Actor *actor = (const Actor *) Sender;
3622 WeaponInfo wi;
3623 unsigned int wrange = 0;
3624 const ITMExtHeader *header = actor->GetWeapon(wi, false);
3625 if (header) {
3626 wrange = actor->GetWeaponRange(wi);
3627 }
3628 // checking also the left hand, in case they're dualwielding
3629 header = actor->GetWeapon(wi, true);
3630 if (header && (wi.range>wrange)) {
3631 wrange = actor->GetWeaponRange(wi);
3632 }
3633 if (WithinPersonalRange(actor, tar, wrange)) {
3634 return 1;
3635 }
3636 return 0;
3637 }
3638
3639 //it is impossible to equip a bow without projectile (it will be fist)
3640 //So outofammo equals fist is equipped
OutOfAmmo(Scriptable * Sender,const Trigger * parameters)3641 int GameScript::OutOfAmmo(Scriptable *Sender, const Trigger *parameters)
3642 {
3643 const Scriptable *scr = Sender;
3644 if (parameters->objectParameter) {
3645 scr = GetActorFromObject( Sender, parameters->objectParameter );
3646 }
3647 if (!scr || scr->Type != ST_ACTOR) {
3648 return 0;
3649 }
3650 const Actor *actor = (const Actor *) scr;
3651
3652 //if a bow is equipped, but out of ammo, the core system will swap to fist anyway
3653 if (actor->inventory.GetEquippedSlot() == actor->inventory.GetFistSlot()) {
3654 return 1;
3655 }
3656
3657 return 0;
3658 }
3659
3660 //returns true if a weapon is equipped and target is in range
3661 //if a bow is equipped without projectile, it is useless (but it will be a fist)!
HaveUsableWeaponEquipped(Scriptable * Sender,const Trigger *)3662 int GameScript::HaveUsableWeaponEquipped(Scriptable *Sender, const Trigger */*parameters*/)
3663 {
3664 if (Sender->Type!=ST_ACTOR) {
3665 return 0;
3666 }
3667 const Actor *actor = (const Actor *) Sender;
3668 //if a bow is equipped, but out of ammo, the core system will swap to fist anyway
3669 if (actor->inventory.GetEquippedSlot() == actor->inventory.GetFistSlot()) {
3670 return 0;
3671 }
3672
3673 return 1;
3674 }
3675
3676 //if the equipped slot is not a fist, this is true
HasWeaponEquipped(Scriptable * Sender,const Trigger * parameters)3677 int GameScript::HasWeaponEquipped(Scriptable *Sender, const Trigger *parameters)
3678 {
3679 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3680 if (!tar || tar->Type!=ST_ACTOR) {
3681 return 0;
3682 }
3683 const Actor *actor = (const Actor *) tar;
3684 if (actor->inventory.GetEquippedSlot() == actor->inventory.GetFistSlot()) {
3685 return 0;
3686 }
3687 return 1;
3688 }
3689
PCInStore(Scriptable *,const Trigger *)3690 int GameScript::PCInStore( Scriptable */*Sender*/, const Trigger */*parameters*/)
3691 {
3692 if (core->GetCurrentStore()) {
3693 return 1;
3694 }
3695 return 0;
3696 }
3697
3698 //this checks if the launch point is onscreen, a more elaborate check
3699 //would see if any piece of the Scriptable is onscreen, what is the original
3700 //behaviour?
OnScreen(Scriptable * Sender,const Trigger *)3701 int GameScript::OnScreen( Scriptable *Sender, const Trigger */*parameters*/)
3702 {
3703 Region vp = core->GetGameControl()->Viewport();
3704 if (vp.PointInside(Sender->Pos) ) {
3705 return 1;
3706 }
3707 return 0;
3708 }
3709
IsPlayerNumber(Scriptable * Sender,const Trigger * parameters)3710 int GameScript::IsPlayerNumber( Scriptable *Sender, const Trigger *parameters)
3711 {
3712 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3713 if (!tar || tar->Type!=ST_ACTOR) {
3714 return 0;
3715 }
3716 const Actor *actor = (const Actor *) tar;
3717 if (actor->InParty == parameters->int0Parameter) {
3718 return 1;
3719 }
3720 return 0;
3721 }
3722
PCCanSeePoint(Scriptable *,const Trigger * parameters)3723 int GameScript::PCCanSeePoint( Scriptable */*Sender*/, const Trigger *parameters)
3724 {
3725 const Map *map = core->GetGame()->GetCurrentArea();
3726 if (map->IsVisible(parameters->pointParameter) ) {
3727 return 1;
3728 }
3729 return 0;
3730 }
3731
3732 // I'm clueless about this trigger ... but it looks fine, pst dgaoha.d is the only user
StuffGlobalRandom(Scriptable * Sender,const Trigger * parameters)3733 int GameScript::StuffGlobalRandom( Scriptable *Sender, const Trigger *parameters)
3734 {
3735 unsigned int max=parameters->int0Parameter+1;
3736 ieDword Value;
3737 if (max) {
3738 Value = RandomNumValue%max;
3739 } else {
3740 Value = RandomNumValue;
3741 }
3742 SetVariable( Sender, parameters->string0Parameter, Value );
3743 if (Value) {
3744 return 1;
3745 }
3746 return 0;
3747 }
3748
IsCreatureAreaFlag(Scriptable * Sender,const Trigger * parameters)3749 int GameScript::IsCreatureAreaFlag( Scriptable *Sender, const Trigger *parameters)
3750 {
3751 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3752 if (!tar || tar->Type!=ST_ACTOR) {
3753 return 0;
3754 }
3755 const Actor *actor = (const Actor *) tar;
3756 if (actor->GetStat(IE_MC_FLAGS) & parameters->int0Parameter) {
3757 return 1;
3758 }
3759 return 0;
3760 }
3761
IsPathCriticalObject(Scriptable * Sender,const Trigger * parameters)3762 int GameScript::IsPathCriticalObject( Scriptable *Sender, const Trigger *parameters)
3763 {
3764 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3765 if (!tar || tar->Type!=ST_ACTOR) {
3766 return 0;
3767 }
3768 const Actor *actor = (const Actor *) tar;
3769 if (actor->GetStat(IE_MC_FLAGS) & MC_PLOT_CRITICAL) {
3770 return 1;
3771 }
3772 return 0;
3773 }
3774
3775 // 0 - ability, 1 - number, 2 - mode
ChargeCount(Scriptable * Sender,const Trigger * parameters)3776 int GameScript::ChargeCount( Scriptable *Sender, const Trigger *parameters)
3777 {
3778 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3779 if (!tar || tar->Type!=ST_ACTOR) {
3780 return 0;
3781 }
3782 const Actor *actor = (const Actor *) tar;
3783 int Slot = actor->inventory.FindItem(parameters->string0Parameter,0);
3784 if (Slot<0) {
3785 return 0;
3786 }
3787 const CREItem *item = actor->inventory.GetSlotItem (Slot);
3788 if (!item) {//bah
3789 return 0;
3790 }
3791 if (parameters->int0Parameter>2) {
3792 return 0;
3793 }
3794 int charge = item->Usages[parameters->int0Parameter];
3795 switch (parameters->int2Parameter) {
3796 case EQUALS:
3797 if (charge == parameters->int1Parameter)
3798 return 1;
3799 break;
3800 case LESS_THAN:
3801 if (charge < parameters->int1Parameter)
3802 return 1;
3803 break;
3804 case GREATER_THAN:
3805 if (charge > parameters->int1Parameter)
3806 return 1;
3807 break;
3808 default:
3809 return 0;
3810 }
3811 return 0;
3812 }
3813
3814 // no idea if it checks only alive partymembers or if it is average or not
CheckPartyLevel(Scriptable *,const Trigger * parameters)3815 int GameScript::CheckPartyLevel( Scriptable */*Sender*/, const Trigger *parameters)
3816 {
3817 if (core->GetGame()->GetTotalPartyLevel(false) < parameters->int0Parameter) {
3818 return 0;
3819 }
3820 return 1;
3821 }
3822
3823 // no idea if it checks only alive partymembers
CheckPartyAverageLevel(Scriptable *,const Trigger * parameters)3824 int GameScript::CheckPartyAverageLevel( Scriptable */*Sender*/, const Trigger *parameters)
3825 {
3826 const Game *game = core->GetGame();
3827
3828 int count = game->GetPartySize(false);
3829 int level = game->GetTotalPartyLevel(false);
3830
3831 if (count) level/=count;
3832
3833 switch (parameters->int1Parameter) {
3834 case EQUALS:
3835 if (level ==parameters->int0Parameter) {
3836 return 1;
3837 }
3838 break;
3839 case LESS_THAN:
3840 if (level < parameters->int0Parameter) {
3841 return 1;
3842 }
3843 break;
3844 case GREATER_THAN:
3845 if (level > parameters->int0Parameter) {
3846 return 1;
3847 }
3848 break;
3849 default:
3850 return 0;
3851 }
3852 return 1;
3853 }
3854
CheckDoorFlags(Scriptable * Sender,const Trigger * parameters)3855 int GameScript::CheckDoorFlags( Scriptable *Sender, const Trigger *parameters)
3856 {
3857 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3858 if (!tar || tar->Type!=ST_DOOR) {
3859 return 0;
3860 }
3861 const Door *door = (const Door *) tar;
3862 if (door->Flags & parameters->int0Parameter) {
3863 return 1;
3864 }
3865 return 0;
3866 }
3867
3868 // works only on animations?
3869 // Be careful when converting to GetActorFromObject, it won't return animations (those are not scriptable)
Frame(Scriptable * Sender,const Trigger * parameters)3870 int GameScript::Frame( Scriptable *Sender, const Trigger *parameters)
3871 {
3872 //to avoid a crash
3873 if (!parameters->objectParameter) {
3874 return 0;
3875 }
3876 const AreaAnimation *anim = Sender->GetCurrentArea()->GetAnimation(parameters->objectParameter->objectName);
3877 if (!anim) {
3878 return 0;
3879 }
3880 int frame = anim->frame;
3881 if ((frame>=parameters->int0Parameter) &&
3882 (frame<=parameters->int1Parameter) ) {
3883 return 1;
3884 }
3885 return 0;
3886 }
3887
3888 //Modalstate in IWD2 allows specifying an object
ModalState(Scriptable * Sender,const Trigger * parameters)3889 int GameScript::ModalState( Scriptable *Sender, const Trigger *parameters)
3890 {
3891 const Scriptable *scr;
3892
3893 if (parameters->objectParameter) {
3894 scr = GetActorFromObject( Sender, parameters->objectParameter );
3895 } else {
3896 scr = Sender;
3897 }
3898 if (!scr || scr->Type!=ST_ACTOR) {
3899 return 0;
3900 }
3901 const Actor *actor = (const Actor *) scr;
3902
3903 if (actor->Modal.State == (ieDword) parameters->int0Parameter) {
3904 return 1;
3905 }
3906 return 0;
3907 }
3908
3909 /* a special redundant trigger for iwd2 - could do something extra */
IsCreatureHiddenInShadows(Scriptable * Sender,const Trigger *)3910 int GameScript::IsCreatureHiddenInShadows( Scriptable *Sender, const Trigger */*parameters*/)
3911 {
3912 if (Sender->Type!=ST_ACTOR) {
3913 return 0;
3914 }
3915 const Actor *actor = (const Actor *) Sender;
3916
3917 if (actor->Modal.State == MS_STEALTH) {
3918 return 1;
3919 }
3920 return 0;
3921 }
3922
IsWeather(Scriptable *,const Trigger * parameters)3923 int GameScript::IsWeather( Scriptable */*Sender*/, const Trigger *parameters)
3924 {
3925 const Game *game = core->GetGame();
3926 ieDword weather = game->WeatherBits & parameters->int0Parameter;
3927 if (weather == (ieDword) parameters->int1Parameter) {
3928 return 1;
3929 }
3930 return 0;
3931 }
3932
Delay(Scriptable * Sender,const Trigger * parameters)3933 int GameScript::Delay( Scriptable *Sender, const Trigger *parameters)
3934 {
3935 ieDword delay = (ieDword) parameters->int0Parameter;
3936 if (delay<=1) {
3937 return 1;
3938 }
3939
3940 return (Sender->ScriptTicks % delay) <= Sender->IdleTicks;
3941 }
3942
3943 #define TIMEOFDAY_DAY 0 /* 7-21 */
3944 #define TIMEOFDAY_DUSK 1 /* 21-22 */
3945 #define TIMEOFDAY_NIGHT 2 /* 22-6 */
3946 #define TIMEOFDAY_MORNING 3 /* 6-7 */
3947
TimeOfDay(Scriptable *,const Trigger * parameters)3948 int GameScript::TimeOfDay(Scriptable */*Sender*/, const Trigger *parameters)
3949 {
3950 int hour = core->Time.GetHour(core->GetGame()->GameTime);
3951
3952 if ((parameters->int0Parameter == TIMEOFDAY_DAY && hour >= 7 && hour < 21)
3953 || (parameters->int0Parameter == TIMEOFDAY_DUSK && hour == 21)
3954 || (parameters->int0Parameter == TIMEOFDAY_NIGHT && (hour >= 22 || hour < 6))
3955 || (parameters->int0Parameter == TIMEOFDAY_MORNING && hour == 6)) {
3956 return 1;
3957 }
3958 return 0;
3959 }
3960
3961 //this is a PST action, it's using delta.ids, not diffmode.ids
RandomStatCheck(Scriptable * Sender,const Trigger * parameters)3962 int GameScript::RandomStatCheck(Scriptable *Sender, const Trigger *parameters)
3963 {
3964 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
3965 if (!tar || tar->Type!=ST_ACTOR) {
3966 return 0;
3967 }
3968 const Actor *actor = (const Actor *) tar;
3969
3970 ieDword stat = actor->GetStat(parameters->int0Parameter);
3971 ieDword value = Bones(parameters->int2Parameter);
3972 switch(parameters->int1Parameter) {
3973 case DM_SET:
3974 if (stat==value)
3975 return 1;
3976 break;
3977 case DM_LOWER:
3978 if (stat<value)
3979 return 1;
3980 break;
3981 case DM_RAISE:
3982 if (stat>value)
3983 return 1;
3984 break;
3985 default:
3986 Log(ERROR, "GameScript", "RandomStatCheck: unknown int parameter 1 passed: %d, ignoring!", parameters->int1Parameter);
3987 break;
3988 }
3989 return 0;
3990 }
3991
PartyRested(Scriptable * Sender,const Trigger *)3992 int GameScript::PartyRested(Scriptable *Sender, const Trigger */*parameters*/)
3993 {
3994 return Sender->MatchTrigger(trigger_partyrested);
3995 }
3996
IsWeaponRanged(Scriptable * Sender,const Trigger * parameters)3997 int GameScript::IsWeaponRanged(Scriptable *Sender, const Trigger *parameters)
3998 {
3999 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4000 if (!tar || tar->Type!=ST_ACTOR) {
4001 return 0;
4002 }
4003 const Actor *actor = (const Actor *) tar;
4004 if (actor->inventory.GetEquipped()<0) {
4005 return 1;
4006 }
4007 return 0;
4008 }
4009
4010 //HoW applies sequence on area animations
Sequence(Scriptable * Sender,const Trigger * parameters)4011 int GameScript::Sequence(Scriptable *Sender, const Trigger *parameters)
4012 {
4013 //to avoid a crash, check if object is NULL
4014 if (parameters->objectParameter) {
4015 const AreaAnimation *anim = Sender->GetCurrentArea()->GetAnimation(parameters->objectParameter->objectName);
4016 if (anim) {
4017 //this is the cycle count for the area animation
4018 //very much like stance for avatar anims
4019 if (anim->sequence==parameters->int0Parameter) {
4020 return 1;
4021 }
4022 return 0;
4023 }
4024 }
4025
4026 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4027 if (!tar || tar->Type != ST_ACTOR) {
4028 return 0;
4029 }
4030 const Actor *actor = (const Actor *) tar;
4031 if (actor->GetStance()==parameters->int0Parameter) {
4032 return 1;
4033 }
4034 return 0;
4035 }
4036
TimerExpired(Scriptable * Sender,const Trigger * parameters)4037 int GameScript::TimerExpired(Scriptable *Sender, const Trigger *parameters)
4038 {
4039 if (Sender->TimerExpired(parameters->int0Parameter) ) {
4040 return 1;
4041 }
4042 return 0;
4043 }
4044
TimerActive(Scriptable * Sender,const Trigger * parameters)4045 int GameScript::TimerActive(Scriptable *Sender, const Trigger *parameters)
4046 {
4047 if (Sender->TimerActive(parameters->int0Parameter) ) {
4048 return 1;
4049 }
4050 return 0;
4051 }
4052
ActuallyInCombat(Scriptable *,const Trigger *)4053 int GameScript::ActuallyInCombat(Scriptable */*Sender*/, const Trigger */*parameters*/)
4054 {
4055 const Game *game = core->GetGame();
4056 if (game->AnyPCInCombat()) return 1;
4057 return 0;
4058 }
4059
InMyGroup(Scriptable * Sender,const Trigger * parameters)4060 int GameScript::InMyGroup(Scriptable *Sender, const Trigger *parameters)
4061 {
4062 if (Sender->Type!=ST_ACTOR) {
4063 return 0;
4064 }
4065
4066 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4067 if (!tar || tar->Type!=ST_ACTOR) {
4068 return 0;
4069 }
4070
4071 if (((const Actor *) tar)->GetStat(IE_SPECIFIC) == ((const Actor *) Sender)->GetStat(IE_SPECIFIC)) {
4072 return 1;
4073 }
4074 return 0;
4075 }
4076
AnyPCSeesEnemy(Scriptable *,const Trigger *)4077 int GameScript::AnyPCSeesEnemy(Scriptable */*Sender*/, const Trigger */*parameters*/)
4078 {
4079 const Game *game = core->GetGame();
4080 unsigned int i = (unsigned int) game->GetLoadedMapCount();
4081 while(i--) {
4082 const Map *map = game->GetMap(i);
4083 if (map->AnyPCSeesEnemy()) {
4084 return 1;
4085 }
4086 }
4087 return 0;
4088 }
4089
Unusable(Scriptable * Sender,const Trigger * parameters)4090 int GameScript::Unusable(Scriptable *Sender, const Trigger *parameters)
4091 {
4092 if (Sender->Type!=ST_ACTOR) {
4093 return 0;
4094 }
4095 const Actor *actor = (const Actor *) Sender;
4096
4097 const Item *item = gamedata->GetItem(parameters->string0Parameter);
4098 if (!item) {
4099 return 0;
4100 }
4101 int ret;
4102 if (actor->Unusable(item)) {
4103 ret = 0;
4104 } else {
4105 ret = 1;
4106 }
4107 gamedata->FreeItem(item, parameters->string0Parameter, true);
4108 return ret;
4109 }
4110
4111 //returns true if the immunity flag is set
4112 //(attacker has to make a successful spell save to hit the target)
IsInGuardianMantle(Scriptable * Sender,const Trigger * parameters)4113 int GameScript::IsInGuardianMantle(Scriptable *Sender, const Trigger *parameters)
4114 {
4115 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4116 if (!tar || tar->Type != ST_ACTOR) {
4117 return 0;
4118 }
4119 const Actor *actor = (const Actor *) tar;
4120 if (actor->GetStat(IE_IMMUNITY)&IMM_GUARDIAN) {
4121 return 1;
4122 }
4123 return 0;
4124 }
4125
HasBounceEffects(Scriptable * Sender,const Trigger * parameters)4126 int GameScript::HasBounceEffects(Scriptable *Sender, const Trigger *parameters)
4127 {
4128 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4129 if (!tar || tar->Type != ST_ACTOR) {
4130 return 0;
4131 }
4132 const Actor *actor = (const Actor *) tar;
4133 if (actor->GetStat(IE_BOUNCE)) return 1;
4134 return 0;
4135 }
4136
HasImmunityEffects(Scriptable * Sender,const Trigger * parameters)4137 int GameScript::HasImmunityEffects(Scriptable *Sender, const Trigger *parameters)
4138 {
4139 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4140 if (!tar || tar->Type != ST_ACTOR) {
4141 return 0;
4142 }
4143 const Actor *actor = (const Actor *) tar;
4144 if (actor->GetStat(IE_IMMUNITY)) return 1;
4145 return 0;
4146 }
4147
4148 // this is a GemRB specific trigger, to transfer some system variables
4149 // to a global (game variable), it will always return true, and the
4150 // variable could be checked in a subsequent trigger (like triggersetglobal)
4151
4152 #define SYSV_SCREENFLAGS 0
4153 #define SYSV_CONTROLSTATUS 1
4154 #define SYSV_REPUTATION 2
4155 #define SYSV_PARTYGOLD 3
4156
SystemVariable_Trigger(Scriptable * Sender,const Trigger * parameters)4157 int GameScript::SystemVariable_Trigger(Scriptable *Sender, const Trigger *parameters)
4158 {
4159 ieDword value;
4160
4161 switch (parameters->int0Parameter) {
4162 case SYSV_SCREENFLAGS:
4163 value = core->GetGameControl()->GetScreenFlags();
4164 break;
4165 case SYSV_CONTROLSTATUS:
4166 value = core->GetGame()->ControlStatus;
4167 break;
4168 case SYSV_REPUTATION:
4169 value = core->GetGame()->Reputation;
4170 break;
4171 case SYSV_PARTYGOLD:
4172 value = core->GetGame()->PartyGold;
4173 break;
4174 default:
4175 return 0;
4176 }
4177
4178 SetVariable(Sender, parameters->string0Parameter, value);
4179 return 1;
4180 }
4181
SpellCast(Scriptable * Sender,const Trigger * parameters)4182 int GameScript::SpellCast(Scriptable *Sender, const Trigger *parameters)
4183 {
4184 return Sender->MatchTriggerWithObject(trigger_spellcast, parameters->objectParameter, parameters->int0Parameter);
4185 }
4186
SpellCastPriest(Scriptable * Sender,const Trigger * parameters)4187 int GameScript::SpellCastPriest(Scriptable *Sender, const Trigger *parameters)
4188 {
4189 return Sender->MatchTriggerWithObject(trigger_spellcastpriest, parameters->objectParameter, parameters->int0Parameter);
4190 }
4191
SpellCastInnate(Scriptable * Sender,const Trigger * parameters)4192 int GameScript::SpellCastInnate(Scriptable *Sender, const Trigger *parameters)
4193 {
4194 return Sender->MatchTriggerWithObject(trigger_spellcastinnate, parameters->objectParameter, parameters->int0Parameter);
4195 }
4196
SpellCastOnMe(Scriptable * Sender,const Trigger * parameters)4197 int GameScript::SpellCastOnMe(Scriptable *Sender, const Trigger *parameters)
4198 {
4199 return Sender->MatchTriggerWithObject(trigger_spellcastonme, parameters->objectParameter, parameters->int0Parameter);
4200 }
4201
CalendarDay(Scriptable *,const Trigger * parameters)4202 int GameScript::CalendarDay(Scriptable */*Sender*/, const Trigger *parameters)
4203 {
4204 int day = core->GetCalendar()->GetCalendarDay(core->GetGame()->GameTime/core->Time.day_size);
4205 if(day == parameters->int0Parameter) {
4206 return 1;
4207 }
4208 return 0;
4209 }
4210
CalendarDayGT(Scriptable *,const Trigger * parameters)4211 int GameScript::CalendarDayGT(Scriptable */*Sender*/, const Trigger *parameters)
4212 {
4213 int day = core->GetCalendar()->GetCalendarDay(core->GetGame()->GameTime/core->Time.day_size);
4214 if(day > parameters->int0Parameter) {
4215 return 1;
4216 }
4217 return 0;
4218 }
4219
CalendarDayLT(Scriptable *,const Trigger * parameters)4220 int GameScript::CalendarDayLT(Scriptable */*Sender*/, const Trigger *parameters)
4221 {
4222 int day = core->GetCalendar()->GetCalendarDay(core->GetGame()->GameTime/core->Time.day_size);
4223 if(day < parameters->int0Parameter) {
4224 return 1;
4225 }
4226 return 0;
4227 }
4228
4229 //NT Returns true only if the active CRE was turned by the specified priest or paladin.
TurnedBy(Scriptable * Sender,const Trigger * parameters)4230 int GameScript::TurnedBy(Scriptable *Sender, const Trigger *parameters)
4231 {
4232 return Sender->MatchTriggerWithObject(trigger_turnedby, parameters->objectParameter);
4233 }
4234
4235 //This is used for pst portals
4236 //usage: UsedExit(Protagonist, "sigil")
4237 //where sigil.2da contains all the exits that should trigger the teleport
UsedExit(Scriptable * Sender,const Trigger * parameters)4238 int GameScript::UsedExit(Scriptable *Sender, const Trigger *parameters)
4239 {
4240 const Scriptable *scr = GetActorFromObject(Sender, parameters->objectParameter);
4241 if (!scr || scr->Type != ST_ACTOR) {
4242 return 0;
4243 }
4244 const Actor *actor = (const Actor *) scr;
4245
4246 if (actor->GetInternalFlag()&IF_USEEXIT) {
4247 return 0;
4248 }
4249
4250 if (!actor->LastArea[0]) {
4251 return 0;
4252 }
4253
4254 AutoTable tm(parameters->string0Parameter);
4255 if (!tm) {
4256 return 0;
4257 }
4258
4259 int count = tm->GetRowCount();
4260 for (int i=0;i<count;i++) {
4261 const char *area = tm->QueryField( i, 0 );
4262 if (strnicmp(actor->LastArea, area, 8) ) {
4263 continue;
4264 }
4265 const char *exit = tm->QueryField( i, 1 );
4266 if (strnicmp(actor->UsedExit, exit, 32) ) {
4267 continue;
4268 }
4269 return 1;
4270 }
4271 return 0;
4272 }
4273
IsTouchGUI(Scriptable *,const Trigger *)4274 int GameScript::IsTouchGUI(Scriptable */*Sender*/, const Trigger */*parameters*/)
4275 {
4276 return EventMgr::TouchInputEnabled;
4277 }
4278
4279 // always evaluates to true on Windows/OS X/Linux (there's no DLC); on other platforms it depends
4280 //TODO: add the real check
HasDLC(Scriptable *,const Trigger *)4281 int GameScript::HasDLC(Scriptable */*Sender*/, const Trigger */*parameters*/)
4282 {
4283 return 1;
4284 }
4285
BeenInParty(Scriptable * Sender,const Trigger *)4286 int GameScript::BeenInParty(Scriptable *Sender, const Trigger */*parameters*/)
4287 {
4288 if (Sender->Type != ST_ACTOR) {
4289 return 0;
4290 }
4291 const Actor *actor = (const Actor *) Sender;
4292 return actor->GetStat(IE_MC_FLAGS) & MC_BEENINPARTY;
4293 }
4294
4295 /*
4296 * TobEx triggers
4297 */
4298
4299 /* Compares the animation movement rate of the target creature specified by Object to Value.
4300 * This is not affected by slow or haste, but is affected if the Object is entangled, webbed, etc.
4301 */
MovementRate(Scriptable * Sender,const Trigger * parameters)4302 int GameScript::MovementRate(Scriptable *Sender, const Trigger *parameters)
4303 {
4304 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4305 if (!tar || tar->Type != ST_ACTOR) {
4306 return 0;
4307 }
4308 const Actor *actor = (const Actor *) tar;
4309
4310 int rate = actor->GetBase(IE_MOVEMENTRATE);
4311 if (actor->Immobile()) {
4312 rate = 0;
4313 }
4314 return rate == parameters->int0Parameter;
4315 }
4316
MovementRateGT(Scriptable * Sender,const Trigger * parameters)4317 int GameScript::MovementRateGT(Scriptable *Sender, const Trigger *parameters)
4318 {
4319 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4320 if (!tar || tar->Type != ST_ACTOR) {
4321 return 0;
4322 }
4323 const Actor *actor = (const Actor *) tar;
4324
4325 int rate = actor->GetBase(IE_MOVEMENTRATE);
4326 if (actor->Immobile()) {
4327 rate = 0;
4328 }
4329 return rate > parameters->int0Parameter;
4330 }
4331
MovementRateLT(Scriptable * Sender,const Trigger * parameters)4332 int GameScript::MovementRateLT(Scriptable *Sender, const Trigger *parameters)
4333 {
4334 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4335 if (!tar || tar->Type != ST_ACTOR) {
4336 return 0;
4337 }
4338 const Actor *actor = (const Actor *) tar;
4339
4340 int rate = actor->GetBase(IE_MOVEMENTRATE);
4341 if (actor->Immobile()) {
4342 rate = 0;
4343 }
4344 return rate < parameters->int0Parameter;
4345 }
4346
4347 // Compares the number of mirror images present on the target creature specified by Object to Value.
NumMirrorImages(Scriptable * Sender,const Trigger * parameters)4348 int GameScript::NumMirrorImages(Scriptable *Sender, const Trigger *parameters)
4349 {
4350 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4351 if (!tar || tar->Type != ST_ACTOR) {
4352 return 0;
4353 }
4354 const Actor *actor = (const Actor *) tar;
4355
4356 return (signed)actor->GetStat(IE_MIRRORIMAGES) == parameters->int0Parameter;
4357 }
4358
NumMirrorImagesGT(Scriptable * Sender,const Trigger * parameters)4359 int GameScript::NumMirrorImagesGT(Scriptable *Sender, const Trigger *parameters)
4360 {
4361 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4362 if (!tar || tar->Type != ST_ACTOR) {
4363 return 0;
4364 }
4365 const Actor *actor = (const Actor *) tar;
4366
4367 return (signed)actor->GetStat(IE_MIRRORIMAGES) > parameters->int0Parameter;
4368 }
4369
NumMirrorImagesLT(Scriptable * Sender,const Trigger * parameters)4370 int GameScript::NumMirrorImagesLT(Scriptable *Sender, const Trigger *parameters)
4371 {
4372 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4373 if (!tar || tar->Type != ST_ACTOR) {
4374 return 0;
4375 }
4376 const Actor *actor = (const Actor *) tar;
4377
4378 return (signed)actor->GetStat(IE_MIRRORIMAGES) < parameters->int0Parameter;
4379 }
4380
4381 /* Returns true if the target creature specified by Object is bouncing spells of power Level.
4382 * This returns true for both Bounce Spell Level (199) and Decrementing Bounce Spells (200) effects.
4383 * (fx_bounce_spelllevel and fx_bounce_spelllevel_dec respectively)
4384 */
4385 static EffectRef fx_level_bounce_ref = { "Bounce:SpellLevel", -1 };
4386 static EffectRef fx_level_bounce_dec_ref = { "Bounce:SpellLevelDec", -1 };
BouncingSpellLevel(Scriptable * Sender,const Trigger * parameters)4387 int GameScript::BouncingSpellLevel(Scriptable *Sender, const Trigger *parameters)
4388 {
4389 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4390 if (!tar || tar->Type != ST_ACTOR) {
4391 return 0;
4392 }
4393 const Actor *actor = (const Actor *) tar;
4394
4395 return actor->fxqueue.HasEffectWithPower(fx_level_bounce_ref, parameters->int0Parameter) ||
4396 actor->fxqueue.HasEffectWithPower(fx_level_bounce_dec_ref, parameters->int0Parameter);
4397 }
4398
4399 /* Compares the number of spell bounces remaining on the target creature specified by Object
4400 * at the power Level to Amount. If Object has the Bounce Spell Level (199) opcode, then the
4401 * number of spell bounces is unsigned 0xFFFFFFFF.
4402 * NOTE: does not check for multiple bounce effects (if that's even possible)
4403 */
NumBouncingSpellLevel(Scriptable * Sender,const Trigger * parameters)4404 int GameScript::NumBouncingSpellLevel(Scriptable *Sender, const Trigger *parameters)
4405 {
4406 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4407 if (!tar || tar->Type != ST_ACTOR) {
4408 return 0;
4409 }
4410 const Actor *actor = (const Actor *) tar;
4411
4412 unsigned int bounceCount = 0;
4413 if (actor->fxqueue.HasEffectWithPower(fx_level_bounce_ref, parameters->int0Parameter)) {
4414 bounceCount = 0xFFFFFFFF;
4415 } else {
4416 const Effect *fx = actor->fxqueue.HasEffectWithPower(fx_level_bounce_dec_ref, parameters->int0Parameter);
4417 if (fx) {
4418 bounceCount = fx->Parameter1;
4419 }
4420 }
4421
4422 return bounceCount == (unsigned) parameters->int1Parameter;
4423 }
4424
NumBouncingSpellLevelGT(Scriptable * Sender,const Trigger * parameters)4425 int GameScript::NumBouncingSpellLevelGT(Scriptable *Sender, const Trigger *parameters)
4426 {
4427 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4428 if (!tar || tar->Type != ST_ACTOR) {
4429 return 0;
4430 }
4431 const Actor *actor = (const Actor *) tar;
4432
4433 unsigned int bounceCount = 0;
4434 if (actor->fxqueue.HasEffectWithPower(fx_level_bounce_ref, parameters->int0Parameter)) {
4435 bounceCount = 0xFFFFFFFF;
4436 } else {
4437 const Effect *fx = actor->fxqueue.HasEffectWithPower(fx_level_bounce_dec_ref, parameters->int0Parameter);
4438 if (fx) {
4439 bounceCount = fx->Parameter1;
4440 }
4441 }
4442
4443 return bounceCount > (unsigned) parameters->int1Parameter;
4444 }
4445
NumBouncingSpellLevelLT(Scriptable * Sender,const Trigger * parameters)4446 int GameScript::NumBouncingSpellLevelLT(Scriptable *Sender, const Trigger *parameters)
4447 {
4448 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4449 if (!tar || tar->Type != ST_ACTOR) {
4450 return 0;
4451 }
4452 const Actor *actor = (const Actor *) tar;
4453
4454 unsigned int bounceCount = 0;
4455 if (actor->fxqueue.HasEffectWithPower(fx_level_bounce_ref, parameters->int0Parameter)) {
4456 bounceCount = 0xFFFFFFFF;
4457 } else {
4458 const Effect *fx = actor->fxqueue.HasEffectWithPower(fx_level_bounce_dec_ref, parameters->int0Parameter);
4459 if (fx) {
4460 bounceCount = fx->Parameter1;
4461 }
4462 }
4463
4464 return bounceCount < (unsigned) parameters->int1Parameter;
4465 }
4466
4467 /* Returns true if the target creature specified by Object is protected from spells of power Level.
4468 * This returns true for both Protection from Spell Levels (102) and Decrementing Spell Immunity (201) effects.
4469 */
4470 static EffectRef fx_level_immunity_ref = { "Protection:Spelllevel", -1 };
4471 static EffectRef fx_level_immunity_dec_ref = { "Protection:SpellLevelDec", -1 };
ImmuneToSpellLevel(Scriptable * Sender,const Trigger * parameters)4472 int GameScript::ImmuneToSpellLevel(Scriptable *Sender, const Trigger *parameters)
4473 {
4474 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4475 if (!tar || tar->Type != ST_ACTOR) {
4476 return 0;
4477 }
4478 const Actor *actor = (const Actor *) tar;
4479
4480 return actor->fxqueue.HasEffectWithPower(fx_level_immunity_ref, parameters->int0Parameter) ||
4481 actor->fxqueue.HasEffectWithPower(fx_level_immunity_dec_ref, parameters->int0Parameter);
4482 }
4483
4484 /* Compares the number of spell protections remaining on the target creature specified by Object
4485 * at the power Level to Amount. If Object has the Protection from Spell Levels (102) opcode,
4486 * then the number of spell protections is unsigned 0xFFFFFFFF.
4487 */
NumImmuneToSpellLevel(Scriptable * Sender,const Trigger * parameters)4488 int GameScript::NumImmuneToSpellLevel(Scriptable *Sender, const Trigger *parameters)
4489 {
4490 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4491 if (!tar || tar->Type != ST_ACTOR) {
4492 return 0;
4493 }
4494 const Actor *actor = (const Actor *) tar;
4495
4496 unsigned int bounceCount = 0;
4497 if (actor->fxqueue.HasEffectWithPower(fx_level_immunity_ref, parameters->int0Parameter)) {
4498 bounceCount = 0xFFFFFFFF;
4499 } else {
4500 const Effect *fx = actor->fxqueue.HasEffectWithPower(fx_level_immunity_dec_ref, parameters->int0Parameter);
4501 if (fx) {
4502 bounceCount = fx->Parameter1;
4503 }
4504 }
4505
4506 return bounceCount == (unsigned) parameters->int1Parameter;
4507 }
4508
NumImmuneToSpellLevelGT(Scriptable * Sender,const Trigger * parameters)4509 int GameScript::NumImmuneToSpellLevelGT(Scriptable *Sender, const Trigger *parameters)
4510 {
4511 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4512 if (!tar || tar->Type != ST_ACTOR) {
4513 return 0;
4514 }
4515 const Actor *actor = (const Actor *) tar;
4516
4517 unsigned int bounceCount = 0;
4518 if (actor->fxqueue.HasEffectWithPower(fx_level_immunity_ref, parameters->int0Parameter)) {
4519 bounceCount = 0xFFFFFFFF;
4520 } else {
4521 const Effect *fx = actor->fxqueue.HasEffectWithPower(fx_level_immunity_dec_ref, parameters->int0Parameter);
4522 if (fx) {
4523 bounceCount = fx->Parameter1;
4524 }
4525 }
4526
4527 return bounceCount > (unsigned) parameters->int1Parameter;
4528 }
4529
NumImmuneToSpellLevelLT(Scriptable * Sender,const Trigger * parameters)4530 int GameScript::NumImmuneToSpellLevelLT(Scriptable *Sender, const Trigger *parameters)
4531 {
4532 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4533 if (!tar || tar->Type != ST_ACTOR) {
4534 return 0;
4535 }
4536 const Actor *actor = (const Actor *) tar;
4537
4538 unsigned int bounceCount = 0;
4539 if (actor->fxqueue.HasEffectWithPower(fx_level_immunity_ref, parameters->int0Parameter)) {
4540 bounceCount = 0xFFFFFFFF;
4541 } else {
4542 const Effect *fx = actor->fxqueue.HasEffectWithPower(fx_level_immunity_dec_ref, parameters->int0Parameter);
4543 if (fx) {
4544 bounceCount = fx->Parameter1;
4545 }
4546 }
4547
4548 return bounceCount < (unsigned) parameters->int1Parameter;
4549 }
4550
4551 // Compares the number of ticks left of time stop to Number.
TimeStopCounter(Scriptable *,const Trigger * parameters)4552 int GameScript::TimeStopCounter(Scriptable */*Sender*/, const Trigger *parameters)
4553 {
4554 return core->GetGame()->RemainingTimestop() == parameters->int0Parameter;
4555 }
4556
TimeStopCounterGT(Scriptable *,const Trigger * parameters)4557 int GameScript::TimeStopCounterGT(Scriptable */*Sender*/, const Trigger *parameters)
4558 {
4559 return core->GetGame()->RemainingTimestop() > parameters->int0Parameter;
4560 }
4561
TimeStopCounterLT(Scriptable *,const Trigger * parameters)4562 int GameScript::TimeStopCounterLT(Scriptable */*Sender*/, const Trigger *parameters)
4563 {
4564 return core->GetGame()->RemainingTimestop() < parameters->int0Parameter;
4565 }
4566
4567 // Returns true if the the target sprite specified by Object is the caster of time stop
TimeStopObject(Scriptable * Sender,const Trigger * parameters)4568 int GameScript::TimeStopObject(Scriptable *Sender, const Trigger *parameters)
4569 {
4570 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4571 if (!tar || tar->Type != ST_ACTOR) {
4572 return 0;
4573 }
4574
4575 return tar == core->GetGame()->GetTimestopOwner();
4576 }
4577
4578 // Compares the number of spell traps remaining on the target creature specified
4579 // by Object at the power Level to Amount.
4580 static EffectRef fx_spelltrap = { "SpellTrap", -1 };
NumTrappingSpellLevel(Scriptable * Sender,const Trigger * parameters)4581 int GameScript::NumTrappingSpellLevel(Scriptable *Sender, const Trigger *parameters)
4582 {
4583 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4584 if (!tar || tar->Type != ST_ACTOR) {
4585 return 0;
4586 }
4587 const Actor *actor = (const Actor *) tar;
4588
4589 int bounceCount = 0;
4590 const Effect *fx = actor->fxqueue.HasEffectWithPower(fx_spelltrap, parameters->int0Parameter);
4591 if (fx) {
4592 bounceCount = fx->Parameter1;
4593 }
4594
4595 return bounceCount == parameters->int1Parameter;
4596 }
4597
NumTrappingSpellLevelGT(Scriptable * Sender,const Trigger * parameters)4598 int GameScript::NumTrappingSpellLevelGT(Scriptable *Sender, const Trigger *parameters)
4599 {
4600 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4601 if (!tar || tar->Type != ST_ACTOR) {
4602 return 0;
4603 }
4604 const Actor *actor = (const Actor *) tar;
4605
4606 int bounceCount = 0;
4607 const Effect *fx = actor->fxqueue.HasEffectWithPower(fx_spelltrap, parameters->int0Parameter);
4608 if (fx) {
4609 bounceCount = fx->Parameter1;
4610 }
4611
4612 return bounceCount > parameters->int1Parameter;
4613 }
4614
NumTrappingSpellLevelLT(Scriptable * Sender,const Trigger * parameters)4615 int GameScript::NumTrappingSpellLevelLT(Scriptable *Sender, const Trigger *parameters)
4616 {
4617 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4618 if (!tar || tar->Type != ST_ACTOR) {
4619 return 0;
4620 }
4621 const Actor *actor = (const Actor *) tar;
4622
4623 int bounceCount = 0;
4624 const Effect *fx = actor->fxqueue.HasEffectWithPower(fx_spelltrap, parameters->int0Parameter);
4625 if (fx) {
4626 bounceCount = fx->Parameter1;
4627 }
4628
4629 return bounceCount < parameters->int1Parameter;
4630 }
4631
4632 // Returns true if the target creature specified by Object is dual-classed and
4633 // the original class matches Class.
OriginalClass(Scriptable * Sender,const Trigger * parameters)4634 int GameScript::OriginalClass(Scriptable *Sender, const Trigger *parameters)
4635 {
4636 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4637 if (!tar || tar->Type != ST_ACTOR) {
4638 return 0;
4639 }
4640 const Actor *actor = (const Actor *) tar;
4641
4642 // we need to look up the bit mapping again
4643 return actor->WasClass(parameters->int0Parameter);
4644 }
4645
4646 // NOTE: HPLost, HPLostGT, HPLostLT are implemented above
4647
4648 /* ASSIGN
4649 * Assigns a value determined by Statement of the type Type from ARGTYPE.IDS (INT integer, or STR string)
4650 * to a local trigger block variable. The general form of Statement is "prefix[params]". This trigger
4651 * does not evaluate and does not count as a trigger in an OR() block.
4652 *
4653 * "prefix" can be: *
4654 * prefix | description | params | type | examples
4655 * c | assigns a constant value | integer or string | c[1], c[FOO]
4656 * e | assigns the value of an expression | expression (see trigger 0x411B Eval() for format) | e[6 + 7]
4657 * id | assigns the index of a IDS file value | file.value | id[EA.CHARMED]
4658 * s | assigns the value of the stat specified of the current object | STATS.IDS name | s[LEVEL]
4659 * sp | assigns the value of the special value specified (of the current object, if applicable) | ASGNSPEC.IDS name | sp[SPRITE_PT_X]
4660 * tn | assigns the value of a 2DA file value by coordinates | file.x.y | tn[IMPORT01.0.0]
4661 * ts | assigns the value of a 2DA file value by column and row name | file.column.row | tn[IMPORT01.ITEMS.1]
4662 * v | assigns the value of a variable | name.scope | v[foo.GLOBAL]
4663 *
4664 * "params" values containing #<num> and @<num> are replaced by the integer and string values,
4665 * respectively, stored in local trigger block variables of index "num". Avoid using integer
4666 * variables in expressions of string type. Avoid using string variables in expressions of integer
4667 * type. The range of "num" is 0 to 24.
4668 */
Assign(Scriptable *,const Trigger *)4669 int GameScript::Assign(Scriptable */*Sender*/, const Trigger */*parameters*/)
4670 {
4671 // TODO: implement
4672 return 0;
4673 }
4674
4675 /* EVAL
4676 * Overwrites the (Loc)th argument of type Type from ARGTYPE.IDS (INT integer, or STR string)
4677 * in the next trigger with the value returned by Expression. This trigger does not evaluate
4678 * and does not count as a trigger in an OR() block. This trigger does not overwrite values of
4679 * the Assign(), NextTriggerObject() and OR() triggers. The NextTriggerObject() trigger ignores
4680 * this trigger.
4681 *
4682 * Expression is a math expression that can use the following symbols: * = + - * / % ^ ( )
4683 * min(x, y), max(x, y), avg(x, y)
4684 * ceil(x), floor(x), round(x)
4685 * abs(x)
4686 * reciprocal(x)
4687 * sqrt(x), pow(x, y)
4688 * log(x), log10(x)
4689 * sin(x), cos(x), tan(x), sinh(x), cosh(x), tanh(x), asin(x), acos(x), atan(x), atan2(x)
4690 * Custom: and(x, y), or(x, y), band(x, y), bor(x, y)
4691 *
4692 * Any text in Expression of form #<num> and @<num> is replaced by the integer and string values,
4693 * respectively, stored in local trigger block variables of index "num". Avoid using integer
4694 * variables in expressions of string type. Avoid using string variables in expressions of integer
4695 * type. The range of "num" is 0 to 24.
4696 */
Eval(Scriptable *,const Trigger *)4697 int GameScript::Eval(Scriptable */*Sender*/, const Trigger */*parameters*/)
4698 {
4699 // TODO: implement
4700 return 0;
4701 }
4702
4703 /* Compares "Num1" to "Num2", where E is equals, GT is greater than, and LT is less than.
4704 * To make use of these triggers, the 0x411B Eval() trigger should be used prior to this trigger.
4705 */
E(Scriptable *,const Trigger * parameters)4706 int GameScript::E(Scriptable */*Sender*/, const Trigger *parameters)
4707 {
4708 return parameters->int0Parameter == parameters->int1Parameter;
4709 }
4710
GT(Scriptable *,const Trigger * parameters)4711 int GameScript::GT(Scriptable */*Sender*/, const Trigger *parameters)
4712 {
4713 return parameters->int0Parameter > parameters->int1Parameter;
4714 }
4715
LT(Scriptable *,const Trigger * parameters)4716 int GameScript::LT(Scriptable */*Sender*/, const Trigger *parameters)
4717 {
4718 return parameters->int0Parameter < parameters->int1Parameter;
4719 }
4720
4721 /*
4722 * End TobEx triggers
4723 */
4724
CurrentAmmo(Scriptable * Sender,const Trigger * parameters)4725 int GameScript::CurrentAmmo(Scriptable *Sender, const Trigger *parameters)
4726 {
4727 const Scriptable *tar = GetActorFromObject(Sender, parameters->objectParameter);
4728 if (!tar || tar->Type != ST_ACTOR) {
4729 return 0;
4730 }
4731 const Actor *actor = (const Actor *) tar;
4732
4733 int eqslot = actor->inventory.GetEquippedSlot();
4734 int effect = core->QuerySlotEffects(eqslot);
4735 if (effect != SLOT_EFFECT_MISSILE) {
4736 return 0;
4737 }
4738
4739 int ammoslot = core->FindSlot(eqslot);
4740 if (ammoslot == -1) {
4741 return 0;
4742 }
4743
4744 return actor->inventory.HasItemInSlot(parameters->string0Parameter, ammoslot);
4745 }
4746
4747 }
4748