Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

rooms.cpp

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-1-0-0/engines/agos/rooms.cpp $
 * $Id: rooms.cpp 43271 2009-08-11 14:50:42Z Kirben $
 *
 */



#include "common/file.h"

#include "agos/agos.h"
#include "agos/intern.h"

using Common::File;

namespace AGOS {

uint16 AGOSEngine::getBackExit(int n) {
      switch (n) {
            case 0:
                  return 2;
            case 1:
                  return 3;
            case 2:
                  return 0;
            case 3:
                  return 1;
            case 4:
                  return 5;
            case 5:
                  return 4;
      }

      return 0;
}

uint16 AGOSEngine::getDoorState(Item *item, uint16 d) {
      uint16 mask = 3;
      uint16 n;

      SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
      if (subRoom == NULL)
            return 0;

      d <<= 1;
      mask <<= d;
      n = subRoom->roomExitStates & mask;
      n >>= d;

      return n;
}

uint16 AGOSEngine::getExitOf(Item *item, uint16 d) {
      SubRoom *subRoom;
      uint16 x;
      uint16 y = 0;

      subRoom = (SubRoom *)findChildOfType(item, kRoomType);
      if (subRoom == NULL)
            return 0;
      x = d;
      while (x > y) {
            if (getDoorState(item, y) == 0)
                  d--;
            y++;
      }
      return subRoom->roomExit[d];
}

void AGOSEngine::changeDoorState(SubRoom *r, uint16 d, uint16 n) {
      uint16 mask=3;
      d <<= 1;
      mask <<= d;
      n <<= d;
      r->roomExitStates &= ~mask;
      r->roomExitStates|= n;
}

void AGOSEngine::setDoorState(Item *i, uint16 d, uint16 n) {
      Item *j;
      SubRoom *r, *r1;
      uint16 d1;
      uint16 y = 0;

      r = (SubRoom *)findChildOfType(i, kRoomType);
      if (r == NULL)
            return;
      d1 = d;
      while (d > y) {
            if (getDoorState(i, y) == 0)
                  d1--;
            y++;
      }
      changeDoorState(r, d, n);

      j = derefItem(r->roomExit[d1]);
      if (j == NULL)
            return;
      r1 = (SubRoom *)findChildOfType(j, kRoomType);
      if (r1 == NULL)
            return;
      d = getBackExit(d);
      d1 = d;
      y = 0;
      while (d > y) {
            if (getDoorState(j, y) == 0)
                  d1--;
            y++;
      }
      /* Check are a complete exit pair */
      if (derefItem(r1->roomExit[d1]) != i)
            return;
      /* Change state of exit coming back */
      changeDoorState(r1, d, n);
}

// Elvira 1 specific
Item *AGOSEngine::getDoorOf(Item *i, uint16 d) {
      SubGenExit *g;
      Item *x;

      g = (SubGenExit *)findChildOfType(i, kGenExitType);
      if (g == NULL)
            return 0;

      x = derefItem(g->dest[d]);
      if (x == NULL)
            return 0;
      if (isRoom(x))
            return 0;
      return x;
}

Item *AGOSEngine::getExitOf_e1(Item *item, uint16 d) {
      SubGenExit *g;
      Item *x;

      g = (SubGenExit *)findChildOfType(item, kGenExitType);
      if (g == NULL)
            return 0;

      x = derefItem(g->dest[d]);
      if (x == NULL)
            return 0;
      if (isRoom(x))
            return x;
      if (x->state != 0)
            return 0;
      return derefItem(x->parent);
}

void AGOSEngine_Waxworks::moveDirn(Item *i, uint x) {
      Item *d;
      uint16 n;

      if (i->parent == 0)
            return;

      n = getExitOf(derefItem(i->parent), x);
      if (derefItem(n) == NULL) {
            loadRoomItems(n);
            n = getExitOf(derefItem(i->parent), x);
      }

      d = derefItem(n);
      if (d) {
            n = getDoorState(derefItem(i->parent), x);
            if (n == 1) {
                  if (!canPlace(i, d))
                        setItemParent(i, d);
            }
      }
}

void AGOSEngine_Elvira2::moveDirn(Item *i, uint x) {
      SubSuperRoom *sr;
      Item *d, *p;
      uint16 a, n;

      if (i->parent == 0)
            return;

      p = derefItem(i->parent);
      if (findChildOfType(p, kSuperRoomType)) {
            n = getExitState(p, _superRoomNumber,x);
            if (n == 1) {
                  sr = (SubSuperRoom *)findChildOfType(p, kSuperRoomType);
                  switch (x) {
                        case 0: a = -(sr->roomX); break;
                        case 1: a = 1; break;
                        case 2: a = sr->roomX; break;
                        case 3: a = 0xFFFF; break;
                        case 4: a = -(sr->roomX * sr->roomY); break;
                        case 5: a = (sr->roomX * sr->roomY); break;
                        default: return;
                  }
                  _superRoomNumber += a;
            }
            return;
      }

      n = getExitOf(derefItem(i->parent), x);

      d = derefItem(n);
      if (d) {
            n = getDoorState(derefItem(i->parent), x);
            if (n == 1) {
                  if (!canPlace(i, d))
                        setItemParent(i, d);
            }
      }
}

void AGOSEngine::moveDirn(Item *i, uint x) {
      Item *d, *p;

      p = derefItem(i->parent);
      if (p == 0)
            return;


      d = getExitOf_e1(p, x);
      if (d) {
            if (canPlace(i, d))
                  return;

            setItemParent(i, d);
            return;
      }

      d = getDoorOf(p, x);
      if (d) {
            const byte *name = getStringPtrByID(d->itemName, true);
            if (d->state == 1)
                  showMessageFormat("%s is closed.\n", name);
            else
                  showMessageFormat("%s is locked.\n", name);
            return;
      }

      showMessageFormat("You can't go that way.\n");
}

// Elvira 2 specific
int AGOSEngine_Elvira2::changeExitStates(SubSuperRoom *sr, int n, int d, uint16 s) {
      int b, bd;
      uint16 mask = 3;
      uint16 bs = s;

      switch (d) {
            case 0:
                  b =- (sr->roomX); bd = 2;
                  if (((n % (sr->roomX * sr->roomY)) / sr->roomX) == 0)
                        return(0);
                  else
                        break;
            case 1:
                  b = 1; bd = 3;
                  if (((n % (sr->roomX * sr->roomY)) % sr->roomX) == 0)
                        return 0;
                  else
                        break;
            case 2:
                  b = sr->roomX; bd = 0;
                  if (((n % (sr->roomX * sr->roomY)) / sr->roomX) == (sr->roomY - 1))
                        return 0;
                  else
                        break;
            case 3:
                  b =- 1; bd = 1;
                  if (((n % (sr->roomX * sr->roomY)) % sr->roomX) == 1)
                        return 0;
                  else
                        break;
            case 4:
                  b =- (sr->roomX * sr->roomY); bd = 5;
                  if (n < (sr->roomX * sr->roomY))
                        return 0;
                  else
                        break;
            case 5:
                  b = sr->roomX * sr->roomY; bd = 4;
                  if (n > (sr->roomX * sr->roomY * (sr->roomZ - 1)))
                        return 0;
                  else
                        break;
            default:
                  return 0;
      }
      n--;
      d <<= 1;
      mask <<= d;
      s <<= d;
      sr->roomExitStates[n] &= ~mask;
      sr->roomExitStates[n] |= s;
      mask = 3;
      n += b;
      bd <<= 1;
      mask <<= bd;
      bs <<= bd;
      sr->roomExitStates[n] &= ~mask;
      sr->roomExitStates[n] |= bs;
      return 1;
}

uint16 AGOSEngine_Elvira2::getExitState(Item *i, uint16 x, uint16 d) {
      SubSuperRoom *sr;
      uint16 mask = 3;
      uint16 n;

      sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
      if (sr == NULL)
            return 0;

      d <<= 1;
      mask <<= d;
      n = sr->roomExitStates[x - 1] & mask;
      n >>= d;
      return n;
}

void AGOSEngine_Elvira2::setExitState(Item *i, uint16 n, uint16 d, uint16 s) {
      SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
      if (sr)
            changeExitStates(sr, n, d, s);
}

void AGOSEngine_Elvira2::setSRExit(Item *i, int n, int d, uint16 s) {
      uint16 mask = 3;

      SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
      if (sr) {
            n--;
            d <<= 1;
            mask <<= d;
            s <<= d;
            sr->roomExitStates[n] &= ~mask;
            sr->roomExitStates[n] |= s;
      }
}

// Waxworks specific
bool AGOSEngine::loadRoomItems(uint16 room) {
      byte *p;
      uint i, minNum, maxNum;
      char filename[30];
      File in;
      Item *item, *itemTmp;

      if (_roomsList == NULL)
            return 0;

      _currentRoom = room;
      room -= 2;

      if (_roomsListPtr) {
            p = _roomsListPtr;
            for (;;) {
                  minNum = READ_BE_UINT16(p); p += 2;
                  if (minNum == 0)
                        break;

                  maxNum = READ_BE_UINT16(p); p += 2;

                   for (uint16 z = minNum; z <= maxNum; z++) {
                        uint16 itemNum = z + 2;
                        item = derefItem(itemNum);
                        item->parent = 0;

                        uint16 num = (itemNum - _itemArrayInited);
                        _roomStates[num].state = item->state;
                        _roomStates[num].classFlags = item->classFlags;
                        SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
                        _roomStates[num].roomExitStates = subRoom->roomExitStates;
                  }
            }
      }

      p = _roomsList;
      while (*p) {
            for (i = 0; *p; p++, i++)
                  filename[i] = *p;
            filename[i] = 0;
            p++;

            for (;;) {
                  _roomsListPtr = p;

                  minNum = READ_BE_UINT16(p); p += 2;
                  if (minNum == 0)
                        break;

                  maxNum = READ_BE_UINT16(p); p += 2;

                  if (room >= minNum && room <= maxNum) {
                        in.open(filename);
                        if (in.isOpen() == false) {
                              error("loadRoomItems: Can't load rooms file '%s'", filename);
                        }

                        while ((i = in.readUint16BE()) != 0) {
                              uint16 itemNum = i + 2;

                              _itemArrayPtr[itemNum] = (Item *)allocateItem(sizeof(Item));
                              readItemFromGamePc(&in, _itemArrayPtr[itemNum]);

                              item = derefItem(itemNum);
                              item->parent = 0;
                              item->child = 0;

                               for (uint16 z = _itemArrayInited; z; z--) {
                                    itemTmp = derefItem(z);

                                    if (!itemTmp)
                                          continue;
                                    if (itemTmp->parent != itemNum)
                                          continue;
                                    if (item->child == 0) {
                                          item->child = z;
                                          continue;
                                    }
                                    uint16 child = item->child;
                                    while (itemTmp->next != 0) {
                                          if (itemTmp->next == child) {
                                                item->child = z;
                                                break;
                                          }

                                          itemTmp = derefItem(itemTmp->next);
                                    }
                              }

                              uint16 num = (itemNum - _itemArrayInited);
                              item->state = _roomStates[num].state;
                              item->classFlags = _roomStates[num].classFlags;
                              SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
                              subRoom->roomExitStates = _roomStates[num].roomExitStates;
                        }
                        in.close();

                        return 1;
                  }
            }
      }

      debug(1,"loadRoomItems: didn't find %d", room);
      return 0;
}

} // End of namespace AGOS

Generated by  Doxygen 1.6.0   Back to index