1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "lastexpress/entities/entity.h"
24
25 #include "lastexpress/data/sequence.h"
26
27 #include "lastexpress/game/action.h"
28 #include "lastexpress/game/entities.h"
29 #include "lastexpress/game/logic.h"
30 #include "lastexpress/game/object.h"
31 #include "lastexpress/game/savegame.h"
32 #include "lastexpress/game/savepoint.h"
33 #include "lastexpress/game/state.h"
34 #include "lastexpress/game/scenes.h"
35
36 #include "lastexpress/lastexpress.h"
37
38 namespace LastExpress {
39
40 //////////////////////////////////////////////////////////////////////////
41 // EntityData
42 //////////////////////////////////////////////////////////////////////////
43
~EntityCallData()44 EntityData::EntityCallData::~EntityCallData() {
45 SAFE_DELETE(frame);
46 SAFE_DELETE(frame1);
47
48 SAFE_DELETE(sequence);
49 SAFE_DELETE(sequence2);
50 SAFE_DELETE(sequence3);
51 }
52
syncString(Common::Serializer & s,Common::String & string,uint length) const53 void EntityData::EntityCallData::syncString(Common::Serializer &s, Common::String &string, uint length) const {
54 assert(length <= 13);
55 assert(string.size() <= 13);
56
57 char seqName[13];
58 memset(&seqName, 0, length);
59
60 if (s.isSaving())
61 strcpy((char *)&seqName, string.c_str());
62
63 s.syncBytes((byte *)&seqName, length);
64
65 if (s.isLoading())
66 string = seqName;
67 }
68
saveLoadWithSerializer(Common::Serializer & s)69 void EntityData::EntityCallData::saveLoadWithSerializer(Common::Serializer &s) {
70 for (uint i = 0; i < ARRAYSIZE(callbacks); i++)
71 s.syncAsByte(callbacks[i]);
72
73 s.syncAsByte(currentCall);
74 s.syncAsUint16LE(entityPosition);
75 s.syncAsUint16LE(location);
76 s.syncAsUint16LE(car);
77 s.syncAsByte(field_497);
78 s.syncAsByte(entity);
79 s.syncAsByte(inventoryItem);
80 s.syncAsByte(direction);
81 s.syncAsUint16LE(field_49B);
82 s.syncAsUint16LE(currentFrame);
83 s.syncAsUint16LE(currentFrame2);
84 s.syncAsUint16LE(field_4A1);
85 s.syncAsUint16LE(field_4A3);
86 s.syncAsByte(clothes);
87 s.syncAsByte(position);
88 s.syncAsByte(car2);
89 s.syncAsByte(doProcessEntity);
90 s.syncAsByte(field_4A9);
91 s.syncAsByte(field_4AA);
92 s.syncAsByte(directionSwitch);
93
94 // Sync strings
95 syncString(s, sequenceName, 13);
96 syncString(s, sequenceName2, 13);
97 syncString(s, sequenceNamePrefix, 7);
98 syncString(s, sequenceNameCopy, 13);
99
100 // Skip pointers to frame & sequences
101 // (we are using a compressed stream, so we cannot seek on load)
102 if (s.isLoading()) {
103 byte empty[5 * 4];
104 s.syncBytes(empty, 5 * 4);
105 } else {
106 s.skip(5 * 4);
107 }
108 }
109
110 //////////////////////////////////////////////////////////////////////////
111 // EntityData
112 //////////////////////////////////////////////////////////////////////////
getParameters(uint callback,byte index) const113 EntityData::EntityParameters *EntityData::getParameters(uint callback, byte index) const {
114 if (callback >= 9)
115 error("[EntityData::getParameters] Invalid callback value (was: %d, max: 9)", callback);
116
117 if (index >= 4)
118 error("[EntityData::getParameters] Invalid index value (was: %d, max: 4)", index);
119
120 return _parameters[callback].parameters[index];
121 }
122
getCallback(uint callback) const123 byte EntityData::getCallback(uint callback) const {
124 if (callback >= 16)
125 error("[EntityData::getCallback] Invalid callback value (was: %d, max: 16)", callback);
126
127 return _data.callbacks[callback];
128 }
129
setCallback(uint callback,byte index)130 void EntityData::setCallback(uint callback, byte index) {
131 if (callback >= 16)
132 error("[EntityData::setCallback] Invalid callback value (was: %d, max: 16)", callback);
133
134 _data.callbacks[callback] = index;
135 }
136
updateParameters(uint32 index) const137 void EntityData::updateParameters(uint32 index) const {
138 if (index < 8)
139 getParameters(8, 0)->update(index);
140 else if (index < 16)
141 getParameters(8, 1)->update(index - 8);
142 else if (index < 24)
143 getParameters(8, 2)->update(index - 16);
144 else if (index < 32)
145 getParameters(8, 3)->update(index - 24);
146 else
147 error("[EntityData::updateParameters] Invalid param index to update (was:%d, max:32)", index);
148 }
149
saveLoadWithSerializer(Common::Serializer & s,const Common::Array<TypeSetter> * paramsTypeSetters)150 void EntityData::saveLoadWithSerializer(Common::Serializer &s, const Common::Array<TypeSetter>* paramsTypeSetters) {
151 if (s.isSaving()) {
152 for (uint i = 0; i < ARRAYSIZE(_parameters); i++)
153 _parameters[i].saveLoadWithSerializer(s);
154
155 _data.saveLoadWithSerializer(s);
156 } else {
157 // to correctly deserialize parameters, we need to know their runtime type
158 // but we don't know it until callbacks[] array will be deserialized
159 // all types of parameters are serialized to 32*4 bytes
160 // (the original game has same-size-PODs and just memcpy-s them.
161 // *sigh* Why does this implementation even need the extra byte in strings?
162 // Well, big-endian vs little-endian is also a thing...)
163 byte buf[ARRAYSIZE(_parameters) * 32 * 4];
164 s.syncBytes(buf, sizeof(buf));
165
166 _data.saveLoadWithSerializer(s);
167
168 for (uint i = 0; i < 8; i++) {
169 if (!paramsTypeSetters || _data.callbacks[i] >= paramsTypeSetters->size())
170 resetParametersType<EntityParametersIIII, EntityParametersIIII, EntityParametersIIII>(&_parameters[i]);
171 else
172 (*paramsTypeSetters)[_data.callbacks[i]](&_parameters[i]);
173 }
174 Common::MemoryReadStream paramsStream(buf, sizeof(buf));
175 Common::Serializer paramsSerializer(¶msStream, NULL);
176 for (uint i = 0; i < ARRAYSIZE(_parameters); i++)
177 _parameters[i].saveLoadWithSerializer(paramsSerializer);
178 }
179 }
180
181 //////////////////////////////////////////////////////////////////////////
182 // Entity
183 //////////////////////////////////////////////////////////////////////////
Entity(LastExpressEngine * engine,EntityIndex index)184 Entity::Entity(LastExpressEngine *engine, EntityIndex index) : _engine(engine), _entityIndex(index) {
185 _data = new EntityData();
186
187 // Add first empty entry to callbacks array
188 _callbacks.push_back(NULL);
189 _paramsTypeSetters.push_back(&EntityData::resetParametersType<EntityData::EntityParametersIIII, EntityData::EntityParametersIIII, EntityData::EntityParametersIIII>);
190 }
191
~Entity()192 Entity::~Entity() {
193 for (uint i = 0; i < _callbacks.size(); i++)
194 SAFE_DELETE(_callbacks[i]);
195
196 _callbacks.clear();
197
198 SAFE_DELETE(_data);
199
200 // Zero-out passed pointers
201 _engine = NULL;
202 }
203
setup(ChapterIndex index)204 void Entity::setup(ChapterIndex index) {
205 switch(index) {
206 case kChapterAll:
207 getSavePoints()->setCallback(_entityIndex, _callbacks[_data->getCurrentCallback()]);
208 break;
209
210 case kChapter1:
211 setup_chapter1();
212 break;
213
214 case kChapter2:
215 setup_chapter2();
216 break;
217
218 case kChapter3:
219 setup_chapter3();
220 break;
221
222 case kChapter4:
223 setup_chapter4();
224 break;
225
226 case kChapter5:
227 setup_chapter5();
228 break;
229
230 default:
231 break;
232 }
233 }
234
235 //////////////////////////////////////////////////////////////////////////
236 // Shared functions
237 //////////////////////////////////////////////////////////////////////////
238
reset(const SavePoint & savepoint,ClothesIndex maxClothes,bool resetItem)239 void Entity::reset(const SavePoint &savepoint, ClothesIndex maxClothes, bool resetItem) {
240 EXPOSE_PARAMS(EntityData::EntityParametersIIII)
241
242 switch (savepoint.action) {
243 default:
244 break;
245
246 case kAction1:
247 if (maxClothes != kClothesDefault) {
248 // Select next available clothes
249 getData()->clothes = (ClothesIndex)(getData()->clothes + 1);
250 if (getData()->clothes > maxClothes)
251 getData()->clothes = kClothesDefault;
252 }
253 break;
254
255 case kActionNone:
256 if (getEntities()->updateEntity(_entityIndex, kCarGreenSleeping, (EntityPosition)params->param1))
257 params->param1 = (params->param1 == 10000) ? 0 : 10000;
258 break;
259
260 case kActionDefault:
261 getData()->entityPosition = kPositionNone;
262 getData()->location = kLocationOutsideCompartment;
263 getData()->car = kCarGreenSleeping;
264
265 if (resetItem)
266 getData()->inventoryItem = kItemInvalid;
267
268 params->param1 = 10000;
269 break;
270 }
271 }
272
savegame(const SavePoint & savepoint)273 void Entity::savegame(const SavePoint &savepoint) {
274 EXPOSE_PARAMS(EntityData::EntityParametersIIII)
275
276 switch (savepoint.action) {
277 default:
278 break;
279
280 case kActionNone:
281 callbackAction();
282 break;
283
284 case kActionDefault:
285 getSaveLoad()->saveGame((SavegameType)params->param1, _entityIndex, (EventIndex)params->param2);
286 callbackAction();
287 break;
288 }
289 }
290
savegameBloodJacket(byte callback)291 bool Entity::savegameBloodJacket(byte callback) {
292 if (getProgress().jacket == kJacketBlood
293 && getEntities()->isDistanceBetweenEntities(_entityIndex, kEntityPlayer, 1000)
294 && !getEntities()->isInsideCompartments(kEntityPlayer)
295 && !getEntities()->checkFields10(kEntityPlayer)) {
296 setCallback(callback);
297 setup_savegame(kSavegameTypeEvent, kEventMertensBloodJacket);
298 return true;
299 }
300 return false;
301 }
302
playSound(const SavePoint & savepoint,bool resetItem,SoundFlag flag)303 void Entity::playSound(const SavePoint &savepoint, bool resetItem, SoundFlag flag) {
304 EXPOSE_PARAMS(EntityData::EntityParametersSIIS)
305
306 switch (savepoint.action) {
307 default:
308 break;
309
310 case kActionEndSound:
311 callbackAction();
312 break;
313
314 case kActionDefault:
315 if (resetItem)
316 getData()->inventoryItem = kItemNone;
317
318 getSound()->playSound(_entityIndex, (char *)¶ms->seq1, flag);
319 break;
320 }
321 }
322
draw(const SavePoint & savepoint,bool handleExcuseMe)323 void Entity::draw(const SavePoint &savepoint, bool handleExcuseMe) {
324 EXPOSE_PARAMS(EntityData::EntityParametersSIIS)
325
326 switch (savepoint.action) {
327 default:
328 break;
329
330 case kActionExitCompartment:
331 callbackAction();
332 break;
333
334 case kActionExcuseMeCath:
335 if (handleExcuseMe && !params->param4) {
336 getSound()->excuseMe(_entityIndex);
337 params->param4 = 1;
338 }
339 break;
340
341 case kActionDefault:
342 getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq1);
343 break;
344 }
345 }
346
draw2(const SavePoint & savepoint)347 void Entity::draw2(const SavePoint &savepoint) {
348 EXPOSE_PARAMS(EntityData::EntityParametersSSII)
349
350 switch (savepoint.action) {
351 default:
352 break;
353
354 case kActionExitCompartment:
355 callbackAction();
356 break;
357
358 case kActionDefault:
359 getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq1);
360 getEntities()->drawSequenceRight((EntityIndex)params->param7, (char *)¶ms->seq2);
361 break;
362 }
363 }
364
updateFromTicks(const SavePoint & savepoint)365 void Entity::updateFromTicks(const SavePoint &savepoint) {
366 EXPOSE_PARAMS(EntityData::EntityParametersIIII)
367
368 switch (savepoint.action) {
369 default:
370 break;
371
372 case kActionNone:
373 if (!Entity::updateParameter(params->param2, getState()->timeTicks, params->param1))
374 break;
375
376 callbackAction();
377 break;
378 }
379 }
380
updateFromTime(const SavePoint & savepoint)381 void Entity::updateFromTime(const SavePoint &savepoint) {
382 EXPOSE_PARAMS(EntityData::EntityParametersIIII)
383
384 switch (savepoint.action) {
385 default:
386 break;
387
388 case kActionNone:
389 if (!Entity::updateParameter(params->param2, getState()->time, params->param1))
390 break;
391
392 callbackAction();
393 break;
394 }
395 }
396
callbackActionOnDirection(const SavePoint & savepoint)397 void Entity::callbackActionOnDirection(const SavePoint &savepoint) {
398 switch (savepoint.action) {
399 default:
400 break;
401
402 case kActionExitCompartment:
403 callbackAction();
404 break;
405
406 case kActionNone:
407 if (getData()->direction != kDirectionRight)
408 callbackAction();
409 break;
410 }
411 }
412
callbackActionRestaurantOrSalon(const SavePoint & savepoint)413 void Entity::callbackActionRestaurantOrSalon(const SavePoint &savepoint) {
414 switch (savepoint.action) {
415 default:
416 break;
417
418 case kActionNone:
419 case kActionDefault:
420 if (getEntities()->isSomebodyInsideRestaurantOrSalon())
421 callbackAction();
422 break;
423 }
424 }
425
updateEntity(const SavePoint & savepoint,bool handleExcuseMe)426 void Entity::updateEntity(const SavePoint &savepoint, bool handleExcuseMe) {
427 EXPOSE_PARAMS(EntityData::EntityParametersIIII)
428
429 switch (savepoint.action) {
430 default:
431 break;
432
433 case kActionExcuseMeCath:
434 if (handleExcuseMe)
435 getSound()->excuseMeCath();
436 break;
437
438 case kActionExcuseMe:
439 if (handleExcuseMe)
440 getSound()->excuseMe(_entityIndex);
441 break;
442
443 case kActionNone:
444 case kActionDefault:
445 if (getEntities()->updateEntity(_entityIndex, (CarIndex)params->param1, (EntityPosition)params->param2))
446 callbackAction();
447 break;
448 }
449 }
450
callSavepoint(const SavePoint & savepoint,bool handleExcuseMe)451 void Entity::callSavepoint(const SavePoint &savepoint, bool handleExcuseMe) {
452 EXPOSE_PARAMS(EntityData::EntityParametersSIIS)
453
454 switch (savepoint.action) {
455 default:
456 break;
457
458 case kActionExitCompartment:
459 if (!CURRENT_PARAM(1, 1))
460 getSavePoints()->call(_entityIndex, (EntityIndex)params->param4, (ActionIndex)params->param5, (char *)¶ms->seq2);
461 callbackAction();
462 break;
463
464 case kActionExcuseMeCath:
465 if (handleExcuseMe && !CURRENT_PARAM(1, 2)) {
466 getSound()->excuseMe(_entityIndex);
467 CURRENT_PARAM(1, 2) = 1;
468 }
469 break;
470
471 case kAction10:
472 if (!CURRENT_PARAM(1, 1)) {
473 getSavePoints()->call(_entityIndex, (EntityIndex)params->param4, (ActionIndex)params->param5, (char *)¶ms->seq2);
474 CURRENT_PARAM(1, 1) = 1;
475 }
476 break;
477
478 case kActionDefault:
479 getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq1);
480 break;
481 }
482 }
483
enterExitCompartment(const SavePoint & savepoint,EntityPosition position1,EntityPosition position2,CarIndex car,ObjectIndex compartment,bool alternate,bool updateLocation)484 void Entity::enterExitCompartment(const SavePoint &savepoint, EntityPosition position1, EntityPosition position2, CarIndex car, ObjectIndex compartment, bool alternate, bool updateLocation) {
485 EXPOSE_PARAMS(EntityData::EntityParametersSIIS)
486
487 switch (savepoint.action) {
488 default:
489 break;
490
491 case kActionExitCompartment:
492 getEntities()->exitCompartment(_entityIndex, (ObjectIndex)params->param4);
493 if (position1)
494 getData()->entityPosition = position1;
495
496 if (updateLocation)
497 getData()->location = kLocationInsideCompartment;
498
499 callbackAction();
500 break;
501
502 case kActionDefault:
503 getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq1);
504 getEntities()->enterCompartment(_entityIndex, (ObjectIndex)params->param4);
505
506 if (position1) {
507 getData()->location = kLocationInsideCompartment;
508
509 if (getEntities()->isInsideCompartment(kEntityPlayer, car, position1) || getEntities()->isInsideCompartment(kEntityPlayer, car, position2)) {
510 getAction()->playAnimation(isNight() ? kEventCathTurningNight : kEventCathTurningDay);
511 getSound()->playSound(kEntityPlayer, "BUMP");
512 getScenes()->loadSceneFromObject(compartment, alternate);
513 }
514 }
515 break;
516 }
517 }
518
goToCompartment(const SavePoint & savepoint,ObjectIndex compartmentFrom,EntityPosition positionFrom,Common::String sequenceFrom,Common::String sequenceTo)519 void Entity::goToCompartment(const SavePoint &savepoint, ObjectIndex compartmentFrom, EntityPosition positionFrom, Common::String sequenceFrom, Common::String sequenceTo) {
520 switch (savepoint.action) {
521 default:
522 break;
523
524 case kActionDefault:
525 getData()->entityPosition = positionFrom;
526 setCallback(1);
527 setup_enterExitCompartment(sequenceFrom.c_str(), compartmentFrom);
528 break;
529
530 case kActionCallback:
531 switch (getCallback()) {
532 default:
533 break;
534
535 case 1:
536 setCallback(2);
537 setup_enterExitCompartment(sequenceTo.c_str(), compartmentFrom);
538 break;
539
540 case 2:
541 getData()->entityPosition = positionFrom;
542 getEntities()->clearSequences(_entityIndex);
543 callbackAction();
544 break;
545 }
546 break;
547 }
548 }
549
goToCompartmentFromCompartment(const SavePoint & savepoint,ObjectIndex compartmentFrom,EntityPosition positionFrom,Common::String sequenceFrom,ObjectIndex compartmentTo,EntityPosition positionTo,Common::String sequenceTo)550 void Entity::goToCompartmentFromCompartment(const SavePoint &savepoint, ObjectIndex compartmentFrom, EntityPosition positionFrom, Common::String sequenceFrom, ObjectIndex compartmentTo, EntityPosition positionTo, Common::String sequenceTo) {
551 switch (savepoint.action) {
552 default:
553 break;
554
555 case kActionDefault:
556 getData()->entityPosition = positionFrom;
557 getData()->location = kLocationOutsideCompartment;
558 setCallback(1);
559 setup_enterExitCompartment(sequenceFrom.c_str(), compartmentFrom);
560 break;
561
562 case kActionCallback:
563 switch (getCallback()) {
564 default:
565 break;
566
567 case 1:
568 setCallback(2);
569 setup_updateEntity(kCarGreenSleeping, positionTo);
570 break;
571
572 case 2:
573 setCallback(3);
574 setup_enterExitCompartment(sequenceTo.c_str(), compartmentTo);
575 break;
576
577 case 3:
578 getData()->location = kLocationInsideCompartment;
579 getEntities()->clearSequences(_entityIndex);
580 callbackAction();
581 break;
582 }
583 break;
584 }
585 }
586
updatePosition(const SavePoint & savepoint,bool handleExcuseMe)587 void Entity::updatePosition(const SavePoint &savepoint, bool handleExcuseMe) {
588 EXPOSE_PARAMS(EntityData::EntityParametersSIII)
589
590 switch (savepoint.action) {
591 default:
592 break;
593
594 case kActionExitCompartment:
595 getEntities()->updatePositionExit(_entityIndex, (CarIndex)params->param4, (Position)params->param5);
596 callbackAction();
597 break;
598
599 case kActionExcuseMeCath:
600 if (handleExcuseMe && !params->param6) {
601 getSound()->excuseMe(_entityIndex);
602 params->param6 = 1;
603 }
604 break;
605
606 case kActionDefault:
607 getEntities()->drawSequenceRight(_entityIndex, (char *)¶ms->seq);
608 getEntities()->updatePositionEnter(_entityIndex, (CarIndex)params->param4, (Position)params->param5);
609 break;
610 }
611 }
612
callbackAction()613 void Entity::callbackAction() {
614 if (getData()->currentCall == 0)
615 error("[Entity::callbackAction] currentCall is already 0, cannot proceed");
616
617 getData()->currentCall--;
618
619 getSavePoints()->setCallback(_entityIndex, _callbacks[_data->getCurrentCallback()]);
620
621 getSavePoints()->call(_entityIndex, _entityIndex, kActionCallback);
622 }
623
624 //////////////////////////////////////////////////////////////////////////
625 // Setup functions
626 //////////////////////////////////////////////////////////////////////////
setup(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter)627 void Entity::setup(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter) {
628 debugC(6, kLastExpressDebugLogic, "Entity: %s()", name);
629
630 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
631 _data->setCurrentCallback(index);
632 paramsTypeSetter(_data->getCurrentCallParameters());
633
634 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
635 }
636
setupI(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,uint param1)637 void Entity::setupI(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1) {
638 debugC(6, kLastExpressDebugLogic, "Entity: %s(%u)", name, param1);
639
640 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
641 _data->setCurrentCallback(index);
642 paramsTypeSetter(_data->getCurrentCallParameters());
643
644 EntityData::EntityParametersIIII *params = (EntityData::EntityParametersIIII *)_data->getCurrentParameters();
645 params->param1 = (unsigned int)param1;
646
647 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
648 }
649
setupII(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,uint param1,uint param2)650 void Entity::setupII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2) {
651 debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %u)", name, param1, param2);
652
653 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
654 _data->setCurrentCallback(index);
655 paramsTypeSetter(_data->getCurrentCallParameters());
656
657 EntityData::EntityParametersIIII *params = (EntityData::EntityParametersIIII *)_data->getCurrentParameters();
658 params->param1 = param1;
659 params->param2 = param2;
660
661 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
662 }
663
setupIII(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,uint param1,uint param2,uint param3)664 void Entity::setupIII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2, uint param3) {
665 debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %u, %u)", name, param1, param2, param3);
666
667 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
668 _data->setCurrentCallback(index);
669 paramsTypeSetter(_data->getCurrentCallParameters());
670
671 EntityData::EntityParametersIIII *params = (EntityData::EntityParametersIIII *)_data->getCurrentParameters();
672 params->param1 = param1;
673 params->param2 = param2;
674 params->param3 = param3;
675
676 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
677 }
678
setupS(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,const char * seq1)679 void Entity::setupS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1) {
680 debugC(6, kLastExpressDebugLogic, "Entity: %s(%s)", name, seq1);
681
682 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
683 _data->setCurrentCallback(index);
684 paramsTypeSetter(_data->getCurrentCallParameters());
685
686 EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS*)_data->getCurrentParameters();
687 strncpy(params->seq1, seq1, 12);
688
689 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
690 }
691
setupSS(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,const char * seq1,const char * seq2)692 void Entity::setupSS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, const char *seq2) {
693 debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %s)", name, seq1, seq2);
694
695 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
696 _data->setCurrentCallback(index);
697 paramsTypeSetter(_data->getCurrentCallParameters());
698
699 EntityData::EntityParametersSSII *params = (EntityData::EntityParametersSSII*)_data->getCurrentParameters();
700 strncpy(params->seq1, seq1, 12);
701 strncpy(params->seq2, seq2, 12);
702
703 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
704 }
705
setupSI(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,const char * seq1,uint param4)706 void Entity::setupSI(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, uint param4) {
707 debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %u)", name, seq1, param4);
708
709 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
710 _data->setCurrentCallback(index);
711 paramsTypeSetter(_data->getCurrentCallParameters());
712
713 EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS *)_data->getCurrentParameters();
714 strncpy(params->seq1, seq1, 12);
715 params->param4 = param4;
716
717 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
718 }
719
setupSII(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,const char * seq1,uint param4,uint param5)720 void Entity::setupSII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, uint param4, uint param5) {
721 debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %u, %u)", name, seq1, param4, param5);
722
723 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
724 _data->setCurrentCallback(index);
725 paramsTypeSetter(_data->getCurrentCallParameters());
726
727 EntityData::EntityParametersSIII *params = (EntityData::EntityParametersSIII *)_data->getCurrentParameters();
728 strncpy(params->seq, seq1, 12);
729 params->param4 = param4;
730 params->param5 = param5;
731
732 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
733 }
734
setupSIII(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,const char * seq,uint param4,uint param5,uint param6)735 void Entity::setupSIII(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq, uint param4, uint param5, uint param6) {
736 debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %u, %u, %u)", name, seq, param4, param5, param6);
737
738 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
739 _data->setCurrentCallback(index);
740 paramsTypeSetter(_data->getCurrentCallParameters());
741
742 EntityData::EntityParametersSIII *params = (EntityData::EntityParametersSIII *)_data->getCurrentParameters();
743 strncpy(params->seq, seq, 12);
744 params->param4 = param4;
745 params->param5 = param5;
746 params->param6 = param6;
747
748 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
749 }
750
setupSIIS(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,const char * seq1,uint param4,uint param5,const char * seq2)751 void Entity::setupSIIS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, uint param4, uint param5, const char *seq2) {
752 debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %u, %u, %s)", name, seq1, param4, param5, seq2);
753
754 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
755 _data->setCurrentCallback(index);
756 paramsTypeSetter(_data->getCurrentCallParameters());
757
758 EntityData::EntityParametersSIIS *params = (EntityData::EntityParametersSIIS *)_data->getCurrentParameters();
759 strncpy(params->seq1, seq1, 12);
760 params->param4 = param4;
761 params->param5 = param5;
762 strncpy(params->seq2, seq2, 12);
763
764 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
765 }
766
setupSSI(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,const char * seq1,const char * seq2,uint param7)767 void Entity::setupSSI(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, const char *seq1, const char *seq2, uint param7) {
768 debugC(6, kLastExpressDebugLogic, "Entity: %s(%s, %s, %u)", name, seq1, seq2, param7);
769
770 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
771 _data->setCurrentCallback(index);
772 paramsTypeSetter(_data->getCurrentCallParameters());
773
774 EntityData::EntityParametersSSII *params = (EntityData::EntityParametersSSII *)_data->getCurrentParameters();
775 strncpy(params->seq1, seq1, 12);
776 strncpy(params->seq2, seq2, 12);
777 params->param7 = param7;
778
779 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
780 }
781
setupIS(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,uint param1,const char * seq)782 void Entity::setupIS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, const char *seq) {
783 debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %s)", name, param1, seq);
784
785 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
786 _data->setCurrentCallback(index);
787 paramsTypeSetter(_data->getCurrentCallParameters());
788
789 EntityData::EntityParametersISII *params = (EntityData::EntityParametersISII *)_data->getCurrentParameters();
790 params->param1 = (unsigned int)param1;
791 strncpy(params->seq, seq, 12);
792
793 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
794 }
795
setupISS(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,uint param1,const char * seq1,const char * seq2)796 void Entity::setupISS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, const char *seq1, const char *seq2) {
797 debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %s, %s)", name, param1, seq1, seq2);
798
799 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
800 _data->setCurrentCallback(index);
801 paramsTypeSetter(_data->getCurrentCallParameters());
802
803 EntityData::EntityParametersISSI *params = (EntityData::EntityParametersISSI *)_data->getCurrentParameters();
804 params->param1 = param1;
805 strncpy(params->seq1, seq1, 12);
806 strncpy(params->seq2, seq2, 12);
807
808 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
809 }
810
setupIIS(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,uint param1,uint param2,const char * seq)811 void Entity::setupIIS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2, const char *seq) {
812 debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %u, %s)", name, param1, param2, seq);
813
814 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
815 _data->setCurrentCallback(index);
816 paramsTypeSetter(_data->getCurrentCallParameters());
817
818 EntityData::EntityParametersIISI *params = (EntityData::EntityParametersIISI *)_data->getCurrentParameters();
819 params->param1 = param1;
820 params->param2 = param2;
821 strncpy(params->seq, seq, 12);
822
823 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
824 }
825
setupIISS(const char * name,uint index,EntityData::TypeSetter paramsTypeSetter,uint param1,uint param2,const char * seq1,const char * seq2)826 void Entity::setupIISS(const char *name, uint index, EntityData::TypeSetter paramsTypeSetter, uint param1, uint param2, const char *seq1, const char *seq2) {
827 debugC(6, kLastExpressDebugLogic, "Entity: %s(%u, %u, %s, %s)", name, param1, param2, seq1, seq2);
828
829 _engine->getGameLogic()->getGameState()->getGameSavePoints()->setCallback(_entityIndex, _callbacks[index]);
830 _data->setCurrentCallback(index);
831 paramsTypeSetter(_data->getCurrentCallParameters());
832
833 EntityData::EntityParametersIISS *params = (EntityData::EntityParametersIISS *)_data->getCurrentParameters();
834 params->param1 = param1;
835 params->param2 = param2;
836 strncpy(params->seq1, seq1, 12);
837 strncpy(params->seq2, seq2, 12);
838
839 _engine->getGameLogic()->getGameState()->getGameSavePoints()->call(_entityIndex, _entityIndex, kActionDefault);
840 }
841
842 //////////////////////////////////////////////////////////////////////////
843 // Helper functions
844 //////////////////////////////////////////////////////////////////////////
845
updateParameter(uint & parameter,uint timeType,uint delta) const846 bool Entity::updateParameter(uint ¶meter, uint timeType, uint delta) const {
847 if (!parameter)
848 parameter = (uint)(timeType + delta);
849
850 if (parameter >= timeType)
851 return false;
852
853 parameter = kTimeInvalid;
854
855 return true;
856 }
857
updateParameterTime(TimeValue timeValue,bool check,uint & parameter,uint delta) const858 bool Entity::updateParameterTime(TimeValue timeValue, bool check, uint ¶meter, uint delta) const {
859 if (getState()->time <= timeValue) {
860 if (check || !parameter)
861 parameter = (uint)(getState()->time + delta);
862 }
863
864 if (parameter >= getState()->time && getState()->time <= timeValue)
865 return false;
866
867 parameter = kTimeInvalid;
868
869 return true;
870 }
871
updateParameterCheck(uint & parameter,uint timeType,uint delta) const872 bool Entity::updateParameterCheck(uint ¶meter, uint timeType, uint delta) const {
873 if (!parameter)
874 parameter = (uint)(timeType + delta);
875
876 if (parameter && parameter >= timeType)
877 return false;
878
879 return true;
880 }
881
timeCheck(TimeValue timeValue,uint & parameter,Common::Functor0<void> * function) const882 bool Entity::timeCheck(TimeValue timeValue, uint ¶meter, Common::Functor0<void> *function) const {
883 if (getState()->time > timeValue && !parameter) {
884 parameter = 1;
885 (*function)();
886
887 return true;
888 }
889
890 return false;
891 }
892
timeCheckCallback(TimeValue timeValue,uint & parameter,byte callback,Common::Functor0<void> * function)893 bool Entity::timeCheckCallback(TimeValue timeValue, uint ¶meter, byte callback, Common::Functor0<void> *function) {
894 if (getState()->time > timeValue && !parameter) {
895 parameter = 1;
896 setCallback(callback);
897 (*function)();
898
899 return true;
900 }
901
902 return false;
903 }
904
timeCheckCallback(TimeValue timeValue,uint & parameter,byte callback,const char * str,Common::Functor1<const char *,void> * function)905 bool Entity::timeCheckCallback(TimeValue timeValue, uint ¶meter, byte callback, const char *str, Common::Functor1<const char *, void> *function) {
906 if (getState()->time > timeValue && !parameter) {
907 parameter = 1;
908 setCallback(callback);
909 (*function)(str);
910
911 return true;
912 }
913
914 return false;
915 }
916
timeCheckCallback(TimeValue timeValue,uint & parameter,byte callback,bool check,Common::Functor1<bool,void> * function)917 bool Entity::timeCheckCallback(TimeValue timeValue, uint ¶meter, byte callback, bool check, Common::Functor1<bool, void> *function) {
918 if (getState()->time > timeValue && !parameter) {
919 parameter = 1;
920 setCallback(callback);
921 (*function)(check);
922
923 return true;
924 }
925
926 return false;
927 }
928
timeCheckCallbackInventory(TimeValue timeValue,uint & parameter,byte callback,Common::Functor0<void> * function)929 bool Entity::timeCheckCallbackInventory(TimeValue timeValue, uint ¶meter, byte callback, Common::Functor0<void> *function) {
930 if (getState()->time > timeValue && !parameter) {
931 parameter = 1;
932 getData()->inventoryItem = kItemNone;
933 setCallback(callback);
934 (*function)();
935
936 return true;
937 }
938
939 return false;
940 }
941
timeCheckCar(TimeValue timeValue,uint & parameter,byte callback,Common::Functor0<void> * function)942 bool Entity::timeCheckCar(TimeValue timeValue, uint ¶meter, byte callback, Common::Functor0<void> *function) {
943 if ((getState()->time <= timeValue && !getEntities()->isPlayerInCar(kCarGreenSleeping)) || !parameter)
944 parameter = (uint)getState()->time + 75;
945
946 if (getState()->time > timeValue || parameter < getState()->time) {
947 parameter = kTimeInvalid;
948 setCallback(callback);
949 (*function)();
950
951 return true;
952 }
953
954 return false;
955 }
956
timeCheckSavepoint(TimeValue timeValue,uint & parameter,EntityIndex entity1,EntityIndex entity2,ActionIndex action) const957 void Entity::timeCheckSavepoint(TimeValue timeValue, uint ¶meter, EntityIndex entity1, EntityIndex entity2, ActionIndex action) const {
958 if (getState()->time > timeValue && !parameter) {
959 parameter = 1;
960 getSavePoints()->push(entity1, entity2, action);
961 }
962 }
963
timeCheckObject(TimeValue timeValue,uint & parameter,ObjectIndex object,ObjectModel model) const964 void Entity::timeCheckObject(TimeValue timeValue, uint ¶meter, ObjectIndex object, ObjectModel model) const {
965 if (getState()->time > timeValue && !parameter) {
966 parameter = 1;
967 getObjects()->updateModel(object, model);
968 }
969 }
970
timeCheckCallbackAction(TimeValue timeValue,uint & parameter)971 bool Entity::timeCheckCallbackAction(TimeValue timeValue, uint ¶meter) {
972 if (getState()->time > timeValue && !parameter) {
973 parameter = 1;
974 callbackAction();
975 return true;
976 }
977
978 return false;
979 }
980
timeCheckPlaySoundUpdatePosition(TimeValue timeValue,uint & parameter,byte callback,const char * sound,EntityPosition position)981 bool Entity::timeCheckPlaySoundUpdatePosition(TimeValue timeValue, uint ¶meter, byte callback, const char* sound, EntityPosition position) {
982 if (getState()->time > timeValue && !parameter) {
983 parameter = 1;
984 getData()->entityPosition = position;
985 setCallback(callback);
986 setup_playSound(sound);
987 return true;
988 }
989
990 return false;
991 }
992
993 } // End of namespace LastExpress
994