aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction/zone.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/parallaction/zone.cpp')
-rw-r--r--engines/parallaction/zone.cpp673
1 files changed, 673 insertions, 0 deletions
diff --git a/engines/parallaction/zone.cpp b/engines/parallaction/zone.cpp
new file mode 100644
index 0000000000..b5eebbba2e
--- /dev/null
+++ b/engines/parallaction/zone.cpp
@@ -0,0 +1,673 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+
+#include "parallaction/parser.h"
+#include "parallaction/parallaction.h"
+#include "parallaction/graphics.h"
+#include "parallaction/inventory.h"
+#include "parallaction/zone.h"
+
+namespace Parallaction {
+
+void freeScript(Program*);
+
+void freeDialogue(Dialogue *d);
+
+Node _zones = { NULL, NULL };
+Node _animations = { NULL, NULL };
+
+Zone *findZone(const char *name) {
+
+ Zone *v4 = (Zone*)_zones._next;
+
+ while (v4) {
+ if (!scumm_stricmp(name, v4->_name)) return v4;
+ v4 = (Zone*)v4->_node._next;
+ }
+
+ Animation *a = findAnimation(name);
+ return (a == NULL ? NULL : &a->_zone);
+}
+
+
+
+
+void Parallaction::parseZone(ArchivedFile *file, Node *list, char *name) {
+// printf("parseZone(%s)\n", name);
+
+ if (findZone(name)) {
+ while (scumm_stricmp(_tokens[0], "endzone")) {
+ parseFillBuffers();
+ }
+ return;
+ }
+
+ Zone *z = (Zone*)memAlloc(sizeof(Zone));
+ memset(z, 0, sizeof(Zone));
+
+ z->_name = (char*)memAlloc(strlen(name)+1);
+ strcpy(z->_name, name);
+
+ addNode(list, &z->_node);
+
+ parseFillBuffers();
+ while (scumm_stricmp(_tokens[0], "endzone")) {
+// printf("token[0] = %s\n", _tokens[0]);
+
+ if (!scumm_stricmp(_tokens[0], "limits")) {
+ z->_limits._left = atoi(_tokens[1]);
+ z->_limits._top = atoi(_tokens[2]);
+ z->_limits._right = atoi(_tokens[3]);
+ z->_limits._bottom = atoi(_tokens[4]);
+ }
+ if (!scumm_stricmp(_tokens[0], "moveto")) {
+ z->_moveTo._x = atoi(_tokens[1]);
+ z->_moveTo._y = atoi(_tokens[2]);
+ }
+ if (!scumm_stricmp(_tokens[0], "type")) {
+ if (_tokens[2][0] != '\0') {
+ z->_type = (4 + searchTable(_tokens[2], _objectsNames)) << 16;
+ }
+ int16 _si = searchTable(_tokens[1], _zoneTypeNames);
+ if (_si != -1) {
+ z->_type |= 1 << (_si - 1);
+ parseZoneTypeBlock(file, z);
+ continue;
+ }
+ }
+ if (!scumm_stricmp(_tokens[0], "commands")) {
+ z->_commands = parseCommands(file);
+ }
+ if (!scumm_stricmp(_tokens[0], "label")) {
+// printf("label: %s\n", _tokens[1]);
+ _vm->_graphics->makeCnvFromString(&z->_label, _tokens[1]);
+ }
+ if (!scumm_stricmp(_tokens[0], "flags")) {
+ uint16 _si = 1;
+
+ do {
+ char _al = searchTable(_tokens[_si], _zoneFlagNames);
+ _si++;
+ z->_flags |= 1 << (_al - 1);
+ } while (!scumm_stricmp(_tokens[_si++], "|"));
+ }
+
+ parseFillBuffers();
+ }
+
+ return;
+}
+
+void freeZones(Node *list) {
+
+ Zone *z = (Zone*)list;
+ Zone *v8 = NULL;
+
+ Node nullNode = { 0, 0 };
+
+ for (; z; z=(Zone*)z->_node._next) {
+
+ // TODO: understand and simplify this monster
+ if (((z->_limits._top == -1) || ((z->_limits._left == -2) && ((isItemInInventory(z->u.merge->_obj1) != 0) || (isItemInInventory(z->u.merge->_obj2) != 0)))) &&
+ (_engineFlags & kEngineQuit) == 0) {
+
+ v8 = (Zone*)z->_node._next;
+ removeNode(&z->_node);
+ addNode(&nullNode, &z->_node);
+ z = v8;
+ continue;
+ }
+
+
+ switch (z->_type & 0xFFFF) {
+ case kZoneExamine:
+ memFree(z->u.examine->_filename);
+ memFree(z->u.examine->_description);
+ memFree(z->u.examine);
+ break;
+
+ case kZoneDoor:
+ memFree(z->u.door->_location);
+ memFree(z->u.door->_background);
+ _vm->_graphics->freeCnv(&z->u.door->_cnv);
+ memFree(z->u.door);
+ break;
+
+ case kZoneSpeak:
+ freeDialogue(z->u.speak->_dialogue);
+ memFree(z->u.speak);
+ break;
+
+ case kZoneGet:
+ memFree(z->u.get->_cnv._data2);
+ _vm->_graphics->freeStaticCnv(&z->u.get->_cnv);
+ memFree(z->u.get);
+ break;
+
+ case kZoneHear:
+ memFree(z->u.hear);
+ break;
+
+ case kZoneMerge:
+ memFree(z->u.merge);
+ break;
+
+ default:
+ break;
+ }
+
+ memFree(z->_name);
+ _vm->_graphics->freeStaticCnv(&z->_label);
+ freeCommands(z->_commands);
+
+ }
+
+ return;
+}
+
+
+
+
+
+
+
+
+
+void Parallaction::parseZoneTypeBlock(ArchivedFile *file, Zone *z) {
+// printf("parseZoneTypeBlock()\n");
+
+ ZoneTypeData *u = &z->u;
+
+ switch (z->_type & 0xFFFF) {
+ case kZoneExamine: // examine Zone alloc
+ u->examine = (ExamineData*)memAlloc(sizeof(ExamineData));
+ memset(u->examine, 0, sizeof(ExamineData));
+ break;
+
+ case kZoneDoor: // door Zone alloc
+ u->door = (DoorData*)memAlloc(sizeof(DoorData));
+ memset(u->door, 0, sizeof(DoorData));
+ break;
+
+ case kZoneGet: // get Zone alloc
+ u->get = (GetData*)memAlloc(sizeof(GetData));
+ memset(u->get, 0, sizeof(GetData));
+ break;
+
+ case kZoneMerge: // merge Zone alloc
+ u->merge = (MergeData*)memAlloc(sizeof(MergeData));
+ memset(u->merge, 0, sizeof(MergeData));
+ break;
+
+ case kZoneHear: // hear Zone alloc
+ u->hear = (HearData*)memAlloc(sizeof(HearData));
+ memset(u->hear, 0, sizeof(HearData));
+ break;
+
+ case kZoneSpeak: // speak Zone alloc
+ u->speak = (SpeakData*)memAlloc(sizeof(SpeakData));
+ memset(u->speak, 0, sizeof(SpeakData));
+ break;
+
+ }
+
+ char vC8[PATH_LEN];
+
+// printf("type = %x\n", z->_type);
+
+ do {
+
+ switch (z->_type & 0xFFFF) {
+ case kZoneExamine: // examine Zone init
+ if (!scumm_stricmp(_tokens[0], "file")) {
+ u->examine->_filename = (char*)memAlloc(strlen(_tokens[1])+1);
+ strcpy(u->examine->_filename, _tokens[1]);
+ }
+ if (!scumm_stricmp(_tokens[0], "desc")) {
+ u->examine->_description = parseComment(file);
+ }
+ break;
+
+ case kZoneDoor: // door Zone init
+ if (!scumm_stricmp(_tokens[0], "slidetext")) {
+ strcpy(_slideText[0], _tokens[1]);
+// printf("%s\t", _slideText[0]);
+ strcpy(_slideText[1], _tokens[2]);
+ }
+
+ if (!scumm_stricmp(_tokens[0], "location")) {
+ u->door->_location = (char*)memAlloc(strlen(_tokens[1])+1);
+ strcpy(u->door->_location, _tokens[1]);
+ }
+
+ if (!scumm_stricmp(_tokens[0], "file")) {
+// printf("file: '%s'\n", _tokens[0]);
+
+ Cnv *doorcnv = &u->door->_cnv;
+ strcpy(vC8, _tokens[1]);
+
+ StaticCnv vE0;
+ _vm->_graphics->loadCnv(vC8, doorcnv);
+
+// printf("door width: %i, height: %i\n", doorcnv->_width, doorcnv->_height );
+
+ vE0._width = doorcnv->_width;
+ vE0._height = doorcnv->_height;
+
+ uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
+ vE0._data0 = doorcnv->_array[_ax];
+
+// _ax = (z->_flags & kFlagsClosed ? 0 : 1);
+// vE0._data1 = doorcnv->field_8[_ax];
+
+ vE0._data2 = u->door->_background = (byte*)memAlloc(vE0._width*vE0._height);
+ _vm->_graphics->backupCnvBackground(&vE0, z->_limits._left, z->_limits._top);
+
+ _vm->_graphics->flatBlitCnv(&vE0, z->_limits._left, z->_limits._top, Graphics::kBitBack, vE0._data1);
+ }
+
+ if (!scumm_stricmp(_tokens[0], "startpos")) {
+ u->door->_startPos._x = atoi(_tokens[1]);
+ u->door->_startPos._y = atoi(_tokens[2]);
+ u->door->_startFrame = atoi(_tokens[3]);
+ }
+ break;
+
+ case kZoneGet: // get Zone init
+ if (!scumm_stricmp(_tokens[0], "file")) {
+ StaticCnv *vE4 = &u->get->_cnv;
+ strcpy(vC8, _tokens[1]);
+ _vm->_graphics->loadStaticCnv(vC8, vE4);
+ vE4->_data2 = (byte*)memAlloc(vE4->_width*vE4->_height);
+
+ if ((z->_flags & kFlagsRemove) == 0) {
+ _vm->_graphics->backupCnvBackgroundTransparent(vE4, z->_limits._left, z->_limits._top);
+ _vm->_graphics->flatBlitCnv(vE4, z->_limits._left, z->_limits._top, Graphics::kBitBack, vE4->_data1);
+ }
+ }
+
+ if (!scumm_stricmp(_tokens[0], "icon")) {
+ u->get->_icon = 4 + searchTable(_tokens[1], _objectsNames);
+ }
+ break;
+
+ case kZoneMerge: // merge Zone init
+ if (!scumm_stricmp(_tokens[0], "obj1")) {
+ u->merge->_obj1 = 4 + searchTable(_tokens[1], _objectsNames);
+ }
+ if (!scumm_stricmp(_tokens[0], "obj2")) {
+ u->merge->_obj2 = 4 + searchTable(_tokens[1], _objectsNames);
+ }
+ if (!scumm_stricmp(_tokens[0], "newobj")) {
+ u->merge->_obj3 = 4 + searchTable(_tokens[1], _objectsNames);
+ }
+ break;
+
+ case kZoneHear: // hear Zone init
+ if (!scumm_stricmp(_tokens[0], "sound")) {
+ strcpy(u->hear->_name, _tokens[1]);
+ }
+ break;
+
+ case kZoneSpeak: // speak Zone init
+ if (!scumm_stricmp(_tokens[0], "file")) {
+ strcpy(u->speak->_name, _tokens[1]);
+// printf("speak file name: %s\n", u.speak._name);
+ }
+ if (!scumm_stricmp(_tokens[0], "Dialogue")) {
+ u->speak->_dialogue = parseDialogue(file);
+ }
+ break;
+ }
+
+ parseFillBuffers();
+ } while (scumm_stricmp(_tokens[0], "endzone"));
+
+ return;
+}
+
+// displays character head commenting an examined object
+//
+// works on the frontbuffer
+//
+void displayCharacterComment(ExamineData *data) {
+ if (data->_description == NULL) return;
+
+// printf("displayCharacterComment()...");
+
+ char v20[20];
+ char *v24 = _vm->_characterName;
+ if (!scumm_strnicmp(v24, "mini", 4)) {
+ v24 += 4;
+ }
+ strcpy(v20, v24);
+
+ if (_engineFlags & kEngineMiniDonna) {
+ sprintf(v20, "%stta", v24);
+ } else {
+ sprintf(v20, "%stal", v24);
+ }
+
+ _vm->_graphics->loadExternalCnv(v20, &_characterFace);
+
+ StaticCnv v3C;
+ v3C._width = _characterFace._width;
+ v3C._height = _characterFace._height;
+ v3C._data0 = _characterFace._array[0];
+// v3C._data1 = _characterFace.field_8[0];
+
+ _vm->_graphics->loadExternalCnv("comiccnv", &Graphics::_font);
+ _vm->_graphics->flatBlitCnv(&v3C, 190, 80, Graphics::kBitFront, v3C._data1);
+
+ int16 v26, v28;
+ _vm->_graphics->getStringExtent(data->_description, 130, &v28, &v26);
+ _vm->_graphics->drawBalloon(140, 10, v28, v26, 0);
+ _vm->_graphics->displayWrappedString(data->_description, 140, 10, 130, 0);
+
+ _vm->_graphics->freeCnv(&Graphics::_font);
+
+// printf("wait left\n");
+
+ waitUntilLeftClick();
+
+ _vm->_graphics->copyScreen(Graphics::kBitBack, Graphics::kBitFront);
+ _vm->_graphics->freeCnv(&_characterFace);
+
+// printf("done\n");
+
+
+ return;
+}
+
+//
+// ZONE TYPE: EXAMINE
+//
+
+// display detail view of an item (and eventually comments)
+//
+// works on the frontbuffer
+//
+
+void displayItemComment(ExamineData *data) {
+
+ if (data->_description == NULL) return;
+
+// printf("displayItemComment()...");
+
+ char v68[PATH_LEN];
+ strcpy(v68, data->_filename);
+ _vm->_graphics->loadStaticCnv(v68, &data->_cnv);
+ _vm->_graphics->flatBlitCnv(&data->_cnv, 140, (SCREEN_HEIGHT - data->_cnv._height)/2, Graphics::kBitFront, data->_cnv._data1);
+ _vm->_graphics->freeStaticCnv(&data->_cnv);
+
+ char *v4 = _vm->_characterName;
+ if (!scumm_strnicmp(v4, "mini", 4)) {
+ v4 += 4;
+ }
+
+ StaticCnv cnv;
+
+ sprintf(v68, "%shead", v4);
+
+ // WORKAROUND
+ // dos file names are in 8.3 format
+ v68[8] = '\0';
+
+ _vm->_graphics->loadExternalStaticCnv(v68, &cnv);
+
+ int16 v6A = 0, v6C = 0;
+
+ _vm->_graphics->loadExternalCnv("comiccnv", &Graphics::_font);
+ _vm->_graphics->getStringExtent(data->_description, 130, &v6C, &v6A);
+ _vm->_graphics->drawBalloon(0, 90, v6C, v6A, 0);
+ _vm->_graphics->flatBlitCnv(&cnv, 100, 152, Graphics::kBitFront, cnv._data1);
+ _vm->_graphics->freeStaticCnv(&cnv);
+ _vm->_graphics->displayWrappedString(data->_description, 0, 90, 130, 0);
+ _vm->_graphics->freeCnv(&Graphics::_font);
+
+ jobEraseAnimations((void*)1, NULL);
+
+ waitUntilLeftClick();
+
+ _vm->_graphics->copyScreen(Graphics::kBitBack, Graphics::kBitFront);
+
+// printf("done\n");
+
+ return;
+}
+
+
+
+uint16 runZone(Zone *z) {
+// printf("runZone('%s')\n", z->_name);
+
+ uint16 subtype = z->_type & 0xFFFF;
+
+// printf("subtype = %x, objecttype = %x\n", subtype, (z->_type & 0xFFFF0000) >> 16);
+ switch(subtype) {
+
+ case kZoneExamine:
+ if (z->u.examine->_filename) {
+ displayItemComment(z->u.examine);
+ } else {
+ displayCharacterComment(z->u.examine);
+ }
+ break;
+
+ case kZoneGet:
+ if (z->_flags & kFlagsFixed) break;
+ if (pickupItem(z) != 0) {
+ return 1;
+ }
+ z->_flags |= kFlagsRemove;
+ break;
+
+ case kZoneDoor:
+ if (z->_flags & kFlagsLocked) break;
+ z->_flags ^= kFlagsClosed;
+ if (z->u.door->_cnv._count == 0) break;
+ addJob(jobToggleDoor, z, JOBPRIORITY_TOGGLEDOOR);
+ break;
+
+ case kZoneHear:
+ strcpy(_soundFile, z->u.hear->_name);
+ break;
+
+ case kZoneSpeak:
+ runDialogue(z->u.speak);
+ break;
+
+ }
+
+// printf("done executing Zone\n");
+
+ return 0;
+}
+
+//
+// ZONE TYPE: DOOR
+//
+void jobToggleDoor(void *parm, Job *j) {
+
+ static byte count = 0;
+
+ Zone *z = (Zone*)parm;
+
+ Cnv *v18 = &z->u.door->_cnv;
+ StaticCnv v14;
+
+ if (v18) {
+ v14._data2 = z->u.door->_background;
+// v4 = &z->u.door._background;
+
+ v14._width = v18->_width;
+ v14._height = v18->_height;
+ _vm->_graphics->restoreCnvBackground(&v14, z->_limits._left, z->_limits._top);
+
+ uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
+
+ v14._data0 = v18->_array[_ax];
+
+ _vm->_graphics->flatBlitCnv(&v14, z->_limits._left, z->_limits._top, Graphics::kBitBack, v14._data1);
+ _vm->_graphics->flatBlitCnv(&v14, z->_limits._left, z->_limits._top, Graphics::kBit2, v14._data1);
+ }
+
+ count++;
+ if (count == 2) {
+ j->_finished = 1;
+ count = 0;
+ }
+
+ return;
+}
+
+
+
+
+
+
+//
+// ZONE TYPE: GET
+//
+
+void jobRemovePickedItem(void *parm, Job *j) {
+
+ Zone *z = (Zone*)parm;
+
+ static uint16 count = 0;
+
+ if (z->u.get->_cnv._width != 0) {
+ _vm->_graphics->restoreCnvBackground(&z->u.get->_cnv, z->_limits._left, z->_limits._top);
+ }
+
+ count++;
+ if (count == 2) {
+ count = 0;
+ j->_finished = 1;
+ }
+
+ return;
+}
+
+void jobDisplayDroppedItem(void *parm, Job *j) {
+// printf("jobDisplayDroppedItem...\n");
+
+ Zone *z = (Zone*)parm;
+
+ if (&z->u.get->_cnv != NULL) {
+ if (z->u.get->_cnv._data0 != NULL) {
+ _vm->_graphics->backupCnvBackgroundTransparent(&z->u.get->_cnv, z->_limits._left, z->_limits._top);
+ }
+
+ _vm->_graphics->flatBlitCnv(&z->u.get->_cnv, z->_limits._left, z->_limits._top, Graphics::kBitBack, z->u.get->_cnv._data1);
+ _vm->_graphics->flatBlitCnv(&z->u.get->_cnv, z->_limits._left, z->_limits._top, Graphics::kBit2, z->u.get->_cnv._data1);
+ }
+
+ j->_count++;
+ if (j->_count == 2) {
+ j->_count = 0;
+ j->_finished = 1;
+ }
+
+// printf("done\n");
+
+ return;
+}
+
+
+
+
+Zone *hitZone(uint32 type, uint16 x, uint16 y) {
+// printf("hitZone(%i, %i, %i)\n", type, x, y);
+
+ uint16 _di = y;
+ uint16 _si = x;
+ Zone *z = (Zone*)_zones._next;
+
+ for (; z; z = (Zone*)z->_node._next) {
+// printf("Zone name: %s\n", z->_name);
+
+ if (z->_flags & kFlagsRemove) continue;
+
+ if ((_si >= z->_limits._right) ||
+ (_si <= z->_limits._left) ||
+ (_di >= z->_limits._bottom) ||
+ (_di <= z->_limits._top)) {
+
+ // out of Zone, so look for special values
+ if ((z->_limits._left == -2) || (z->_limits._left == -3)) {
+ // only merge zones have _left == -2 or _left == -3
+
+ if (((_si == z->u.merge->_obj1) && (_di == z->u.merge->_obj2)) ||
+ ((_si == z->u.merge->_obj2) && (_di == z->u.merge->_obj1))) {
+
+ // special Zone
+ if ((type == 0) && ((z->_type & 0xFFFF0000) == 0)) return z;
+ if (z->_type == type) return z;
+ if ((z->_type & 0xFFFF0000) == type) return z;
+
+ }
+ }
+
+ if (z->_limits._left != -1) continue;
+ if (_si < _yourself._zone.pos._position._x) continue;
+ if (_si > (_yourself._zone.pos._position._x + _yourself._cnv._width)) continue;
+ if (_di < _yourself._zone.pos._position._y) continue;
+ if (_di > (_yourself._zone.pos._position._y + _yourself._cnv._height)) continue;
+
+ }
+
+ // normal Zone
+ if ((type == 0) && ((z->_type & 0xFFFF0000) == 0)) return z;
+ if (z->_type == type) return z;
+ if ((z->_type & 0xFFFF0000) == type) return z;
+
+ }
+
+ Animation *a = (Animation*)_animations._next;
+
+ int16 _a, _b, _c, _d, _e, _f;
+ for (; a; a = (Animation*)a->_zone._node._next) {
+// printf("Animation name: %s\n", a->_zone._name);
+
+ _a = (a->_zone._flags & kFlagsActive) ? 1 : 0; // _a: active Animation
+ _e = ((_si >= a->_zone.pos._position._x + a->_cnv._width) || (_si <= a->_zone.pos._position._x)) ? 0 : 1; // _e: horizontal range
+ _f = ((_di >= a->_zone.pos._position._y + a->_cnv._height) || (_di <= a->_zone.pos._position._y)) ? 0 : 1; // _f: vertical range
+
+ _b = ((type != 0) || (a->_zone._type == kZoneYou)) ? 0 : 1; // _b: (no type specified) AND (Animation is not the character)
+ _c = (a->_zone._type & 0xFFFF0000) ? 0 : 1; // _c: Animation is not an object
+ _d = ((a->_zone._type & 0xFFFF0000) != type) ? 0 : 1; // _d: Animation is an object of the same type
+
+ if ((_a != 0 && _e != 0 && _f != 0) && ((_b != 0 && _c != 0) || (a->_zone._type == type) || (_d != 0))) {
+
+ return &a->_zone;
+
+ }
+
+ }
+
+ return NULL;
+
+}
+
+} // namespace Parallaction