home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 February / chip_20022115.iso / amiga / chipgame / scummvm_aga.lha / ScummVM_AGA / src / object.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-01-05  |  19.3 KB  |  808 lines

  1. /* ScummVM - Scumm Interpreter
  2.  * Copyright (C) 2001  Ludvig Strigeus
  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  *
  18.  * $Header: /cvsroot/scummvm/scummvm/object.cpp,v 1.12 2001/11/07 18:10:51 strigeus Exp $
  19.  *
  20.  */
  21.  
  22. #include "stdafx.h"
  23. #include "scumm.h"
  24.  
  25. bool Scumm::getClass(int obj, int cls) {
  26.     checkRange(_numGlobalObjects-1, 0, obj, "Object %d out of range in getClass");
  27.  
  28.     cls &= 0x7F;
  29.     checkRange(32,1,cls,"Class %d out of range in getClass");
  30.  
  31.     return (_classData[obj] & (1<<(cls-1))) != 0;
  32. }
  33.  
  34. void Scumm::putClass(int obj, int cls, bool set) {
  35.     checkRange(_numGlobalObjects-1, 0, obj, "Object %d out of range in getClass");
  36.  
  37.     cls &= 0x7F;
  38.     checkRange(32,1,cls,"Class %d out of range in getClass");
  39.  
  40.     if (set)
  41.         _classData[obj] |= (1<<(cls-1));
  42.     else
  43.         _classData[obj] &= ~(1<<(cls-1));
  44. }
  45.  
  46. int Scumm::getOwner(int obj) {
  47.     checkRange(_numGlobalObjects-1, 0, obj, "Object %d out of range in getOwner");
  48.     return _objectFlagTable[obj]&0xF;
  49. }
  50.  
  51. void Scumm::putOwner(int act, int owner) {
  52.     checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in putOwner");
  53.     checkRange(15, 0, owner, "Owner %d out of range in putOwner");
  54.     _objectFlagTable[act] = (_objectFlagTable[act]&0xF0) | owner;
  55. }
  56.  
  57. int Scumm::getState(int act) {
  58.     checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in getState");
  59.     return _objectFlagTable[act]>>4;
  60. }
  61.  
  62. void Scumm::putState(int act, int state) {
  63.     checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in putState");
  64.     checkRange(15, 0, state, "State %d out of range in putState");
  65.     _objectFlagTable[act] = (_objectFlagTable[act]&0x0F) | (state<<4);
  66. }
  67.  
  68. int Scumm::getObjectIndex(int object) {
  69.     int i;
  70.  
  71.     if ((_objectFlagTable[object]&0xF)!=0xF) {
  72.         for (i=0; i<_maxInventoryItems; i++)
  73.             if (_inventory[i] == object)
  74.                 return i;
  75.         return -1;
  76.     } else {
  77.         for (i=_numObjectsInRoom; i>0; i--) {
  78.             if (_objs[i].obj_nr==object)
  79.                 return i;
  80.         }
  81.         return -1;
  82.     }
  83. }
  84.  
  85. int Scumm::whereIsObject(int object) {
  86.     int i;
  87.  
  88.     if (object >= _numGlobalObjects)
  89.         return -1;
  90.  
  91.     if ((_objectFlagTable[object]&0xF)!=0xF) {
  92.         for (i=0; i<_maxInventoryItems; i++)
  93.             if (_inventory[i] == object)
  94.                 return 0;
  95.         return -1;
  96.     }
  97.  
  98.     for (i=_numObjectsInRoom; i>0; i--)
  99.         if (_objs[i].obj_nr == object) {
  100.             if (_objs[i].fl_object_index)
  101.                 return 4;
  102.             return 1;
  103.         }
  104.     return -1;
  105. }
  106.  
  107. int Scumm::getObjectOrActorXY(int object) {
  108.     if (object <= _vars[VAR_NUM_ACTOR]) {
  109.         return getActorXYPos(derefActorSafe(object, "getObjectOrActorXY"));
  110.     }
  111.     switch(whereIsObject(object)) {
  112.     case -1:
  113.         return -1;
  114.     case 0:
  115.         return getActorXYPos(derefActorSafe(_objectFlagTable[object]&0xF,"getObjectOrActorXY(2)"));
  116.     }
  117.     getObjectXYPos(object);
  118.     return 0;
  119. }
  120.  
  121. void Scumm::getObjectXYPos(int object) {
  122.     ObjectData *od = &_objs[getObjectIndex(object)];
  123.     int state;
  124.     byte *ptr;
  125.     ImageHeader *imhd;
  126.     int x,y;
  127.     AdjustBoxResult abr;
  128.  
  129.     if (_majorScummVersion==6) {
  130.         state = getState(object)-1;
  131.         if (state<0)
  132.             state = 0;
  133.  
  134.         if (od->fl_object_index) {
  135.             ptr = getResourceAddress(rtFlObject, od->fl_object_index);
  136.             ptr = findResource(MKID('OBIM'), ptr, 0);
  137.         } else {
  138.             ptr = getResourceAddress(rtRoom, _roomResource);
  139.             ptr += od->offs_obim_to_room;
  140.         }
  141.  
  142.         imhd = (ImageHeader*)findResource(MKID('IMHD'), ptr, 0);
  143.         x = od->x_pos*8 + (int16)READ_LE_UINT16(&imhd->hotspot[state].x);
  144.         y = od->y_pos*8 + (int16)READ_LE_UINT16(&imhd->hotspot[state].y);
  145.     } else {
  146.         x = od->walk_x;
  147.         y = od->walk_y;
  148.     }
  149.  
  150.     abr = adjustXYToBeInBox(0, x, y);
  151.     _xPos = abr.x;
  152.     _yPos = abr.y;
  153.     _dir = od->actordir&3;
  154. }
  155.  
  156. int Scumm::getObjActToObjActDist(int a, int b) {
  157.     int x,y;
  158.     Actor *acta = NULL;
  159.     Actor *actb = NULL;
  160.  
  161.     if (a<=_vars[VAR_NUM_ACTOR])
  162.         acta = derefActorSafe(a, "getObjActToObjActDist");
  163.  
  164.     if (b<=_vars[VAR_NUM_ACTOR])
  165.         actb = derefActorSafe(b, "getObjActToObjActDist(2)");
  166.  
  167.     if (acta && actb && acta->room==actb->room && acta->room &&
  168.         acta->room != _currentRoom)
  169.             return 0xFF;
  170.  
  171.     if (getObjectOrActorXY(a)==-1)
  172.         return 0xFF;
  173.  
  174.     x = _xPos;
  175.     y = _yPos;
  176.  
  177.     if (getObjectOrActorXY(b)==-1)
  178.         return 0xFF;
  179.  
  180.     if (acta) {
  181.         AdjustBoxResult r = adjustXYToBeInBox(acta, _xPos, _yPos);
  182.         _xPos = r.x;
  183.         _yPos = r.y;
  184.     }
  185.  
  186.     y = abs(y-_yPos);
  187.     x = abs(x-_xPos);
  188.  
  189.     if (y>x) x=y;
  190.     return x;
  191. }
  192.  
  193. int Scumm::findObject(int x, int y) {
  194.     int i,a,b;
  195.  
  196.     for (i=1; i<=_numObjectsInRoom; i++) {
  197.         if (!_objs[i].obj_nr || getClass(_objs[i].obj_nr, 32))
  198.             continue;
  199.         b = i;
  200.         do {
  201.             a = _objs[b].parentstate;
  202.             b = _objs[b].parent;
  203.             if (b==0) {
  204.                 if (_objs[i].x_pos <= (x>>3) &&
  205.                         _objs[i].numstrips + _objs[i].x_pos > (x>>3) &&
  206.                         _objs[i].y_pos <= (y>>3) &&
  207.                         _objs[i].height + _objs[i].y_pos > (y>>3))
  208.                         return _objs[i].obj_nr;
  209.                 break;
  210.             }
  211.         } while ( (_objs[b].ownerstate&0xF0) == a);
  212.     }
  213.     return 0;
  214. }
  215.  
  216. void Scumm::drawRoomObjects(int arg) {
  217.     int num = _numObjectsInRoom;
  218.     ObjectData *od;
  219.     int a;
  220.  
  221.     if (num==0)
  222.         return;
  223.  
  224.     do {
  225.         od = &_objs[num];
  226.         if (!od->obj_nr || !(od->ownerstate&0xF0))
  227.             continue;
  228.         
  229.         do {
  230.             a = od->parentstate;
  231.             if (!od->parent) {
  232.                 drawObject(num, arg);
  233.                 break;
  234.             }
  235.             od = &_objs[od->parent];
  236.         } while ((od->ownerstate & 0xF0)==a);
  237.  
  238.     } while (--num);
  239. }
  240.  
  241. const uint32 state_tags[] = {
  242.     MKID('IM00'),
  243.     MKID('IM01'),
  244.     MKID('IM02'),
  245.     MKID('IM03'),
  246.     MKID('IM04'),
  247.     MKID('IM05'),
  248.     MKID('IM06'),
  249.     MKID('IM07'),
  250.     MKID('IM08'),
  251.     MKID('IM09'),
  252.     MKID('IM0A'),
  253.     MKID('IM0B'),
  254.     MKID('IM0C'),
  255.     MKID('IM0D'),
  256.     MKID('IM0E'),
  257.     MKID('IM0F')
  258. };
  259.  
  260. void Scumm::drawObject(int obj, int arg) {
  261.     ObjectData *od;
  262.     int xpos, ypos, height, width;
  263.     byte *ptr;
  264.     int x,a,numstrip;
  265.     int tmp;
  266.  
  267.     if (_BgNeedsRedraw)
  268.         arg = 0;
  269.  
  270.     _curVirtScreen = &virtscr[0];
  271.     
  272.     od = &_objs[obj];
  273.  
  274.     xpos = od->x_pos;
  275.     ypos = od->y_pos;
  276.     width = od->numstrips;
  277.     height = od->height;
  278.  
  279.     if (width==0 || xpos > _screenEndStrip || xpos + width < _screenStartStrip)
  280.         return;
  281.     
  282.     if (od->fl_object_index) {
  283.         ptr = getResourceAddress(rtFlObject, od->fl_object_index);
  284.         ptr = findResource(MKID('OBIM'), ptr, 0); 
  285.     } else {
  286.         ptr = getResourceAddress(rtRoom, _roomResource);
  287.         ptr = ptr + od->offs_obim_to_room;
  288.     }
  289.  
  290.     ptr = findResource(state_tags[getState(od->obj_nr)], ptr, 0);
  291.     if (!ptr)
  292.         return;
  293.  
  294.     x = 0xFFFF;
  295.  
  296.     for (a=numstrip=0; a<width; a++) {
  297.         tmp = xpos + a;
  298.         if (arg==1 && _screenStartStrip!=tmp)
  299.             continue;
  300.         if (arg==2 && _screenEndStrip!=tmp)
  301.             continue;
  302.         if (tmp < _screenStartStrip || tmp > _screenEndStrip)
  303.             continue;
  304.         actorDrawBits[tmp] |= 0x8000;
  305.         if (tmp < x)
  306.             x = tmp;
  307.         numstrip++;
  308.     }
  309.  
  310.     if (numstrip!=0)
  311.         gdi.drawBitmap(ptr, _curVirtScreen, x, ypos<<3, height<<3, x-xpos, numstrip, true);
  312.  
  313. //    _drawBmpY = ypos << 3;
  314. //    gdi._numLinesToProcess = height << 3;
  315. //    _drawBmpX = x;
  316. //    drawBmp(ptr, x - xpos, b, 1, "Object", od->obj_nr);
  317. }
  318.  
  319. void Scumm::loadRoomObjects() {
  320.     int i,j;
  321.     ObjectData *od;
  322.     byte *ptr;
  323.     uint16 obim_id;
  324.     byte *room;
  325.     ImageHeader *imhd;
  326.     RoomHeader *roomhdr;
  327.  
  328.     CodeHeader *cdhd;
  329.  
  330.     CHECK_HEAP
  331.     
  332.     room = getResourceAddress(rtRoom, _roomResource);
  333.     roomhdr = (RoomHeader*)findResource(MKID('RMHD'), room, 0);
  334.  
  335.     _numObjectsInRoom = READ_LE_UINT16(&roomhdr->numObjects);
  336.     
  337.     if (_numObjectsInRoom == 0)
  338.         return;
  339.     
  340.     if (_numObjectsInRoom > _numLocalObjects)
  341.         error("More than %d objects in room %d", _numLocalObjects, _roomResource);
  342.  
  343.     od = &_objs[1];
  344.     for (i=0; i<_numObjectsInRoom; i++,od++) {
  345.         ptr = findResource(MKID('OBCD'), room, i);
  346.         if (ptr==NULL)
  347.             error("Room %d missing object code block(s)", _roomResource);
  348.  
  349.         od->offs_obcd_to_room = ptr - room;
  350.         cdhd = (CodeHeader*)findResource(MKID('CDHD'), ptr, 0);
  351.         od->obj_nr = READ_LE_UINT16(&cdhd->obj_id);
  352.  
  353. #ifdef DUMP_SCRIPTS
  354.         do {
  355.             char buf[32];
  356.             sprintf(buf,"roomobj-%d-",_roomResource);
  357.             dumpResource(buf, od->obj_nr, ptr);
  358.         } while (0);
  359. #endif
  360.     }
  361.  
  362.     for (i=0; i<_numObjectsInRoom; i++) {
  363.         ptr = findResource(MKID('OBIM'), room, i);
  364.         if (ptr==NULL)
  365.             error("Room %d missing image blocks(s)", _roomResource);
  366.  
  367.         imhd = (ImageHeader*)findResource(MKID('IMHD'), ptr, 0);
  368.         obim_id = READ_LE_UINT16(&imhd->obj_id);
  369.  
  370.         for(j=1; j<=_numObjectsInRoom; j++) {
  371.             if (_objs[j].obj_nr==obim_id)
  372.                 _objs[j].offs_obim_to_room = ptr - room;
  373.         }
  374.     }
  375.  
  376.     od = &_objs[1];
  377.     for (i=1; i<=_numObjectsInRoom; i++,od++) {
  378.         ptr = room + od->offs_obcd_to_room;
  379.         cdhd = (CodeHeader*)findResource(MKID('CDHD'), ptr,0);
  380.         od->obj_nr = READ_LE_UINT16(&cdhd->obj_id);
  381.  
  382.         if (_majorScummVersion == 6) {
  383.             od->numstrips = READ_LE_UINT16(&cdhd->v6.w)>>3;
  384.             od->height = READ_LE_UINT16(&cdhd->v6.h)>>3;
  385.             od->x_pos = ((int16)READ_LE_UINT16(&cdhd->v6.x))>>3;
  386.             od->y_pos = ((int16)READ_LE_UINT16(&cdhd->v6.y))>>3;
  387.             if (cdhd->v6.flags == 0x80) {
  388.                 od->parentstate = 1<<4;
  389.             } else {
  390.                 od->parentstate = (cdhd->v6.flags&0xF)<<4;
  391.             }
  392.             od->parent = cdhd->v6.parent;
  393.             od->actordir = cdhd->v6.actordir;
  394.         } else {
  395.             od->numstrips = cdhd->v5.w;
  396.             od->height = cdhd->v5.h;
  397.             od->x_pos = cdhd->v5.x;
  398.             od->y_pos = cdhd->v5.y;
  399.             if (cdhd->v5.flags == 0x80) {
  400.                 od->parentstate = 1<<4;
  401.             } else {
  402.                 od->parentstate = (cdhd->v5.flags&0xF)<<4;
  403.             }
  404.             od->parent = cdhd->v5.parent;
  405.             od->walk_x = READ_LE_UINT16(&cdhd->v5.walk_x);
  406.             od->walk_y = READ_LE_UINT16(&cdhd->v5.walk_y);
  407.             od->actordir = cdhd->v5.actordir;
  408.         }
  409.         od->fl_object_index = 0;
  410.     }
  411.  
  412.     CHECK_HEAP
  413. }
  414.  
  415. void Scumm::fixObjectFlags() {
  416.     int i;
  417.     ObjectData *od = &_objs[1];
  418.     for (i=1; i<=_numObjectsInRoom; i++,od++) {
  419.         od->ownerstate = _objectFlagTable[od->obj_nr];
  420.     }
  421. }
  422.  
  423. void Scumm::processDrawQue() {
  424.     int i, j;
  425.     for (i=0; i<_drawObjectQueNr; i++) {
  426.         j = _drawObjectQue[i];
  427.         if (j)
  428.             drawObject(j,0);
  429.     }
  430.     _drawObjectQueNr = 0;
  431. }
  432.  
  433. void Scumm::clearOwnerOf(int obj) {
  434.     int i,j;
  435.     uint16 *a;
  436.     byte *ptr;
  437.  
  438.     stopObjectScript(obj);
  439.     
  440.     if (getOwner(obj)==0xF) {
  441.         i = 0;
  442.         do {
  443.             if (_objs[i].obj_nr==obj) {
  444.                 if (!_objs[i].fl_object_index)
  445.                     return;
  446.                 nukeResource(rtFlObject, _objs[i].fl_object_index);
  447.                 _objs[i].obj_nr = 0;
  448.                 _objs[i].fl_object_index = 0;
  449.             }
  450.         } while(++i <= _numObjectsInRoom);
  451.         return;
  452.     }
  453.     for (i=1; i<_maxInventoryItems; i++) {
  454.         if (_inventory[i] == obj) {
  455.             j = whereIsObject(obj);
  456.             if (j==0) {
  457.                 nukeResource(rtInventory, i);
  458.                 _inventory[i] = 0;
  459.             }
  460.             a = &_inventory[1];
  461.             for (i=1; i < _maxInventoryItems-1; i++,a++) {
  462.                 if (!a[0] && a[1]) {
  463.                     a[0] = a[1];
  464.                     a[1] = 0;
  465.                     ptr = getResourceAddress(rtInventory, i+1);
  466.                     _baseInventoryItems[i] = _baseInventoryItems[i+1];
  467.                     _baseInventoryItems[i+1] = 0;
  468.                     /* TODO: some wacky write is done here */
  469.                 }
  470.             }
  471.             return;
  472.         }
  473.     }
  474. }
  475.  
  476. void Scumm::removeObjectFromRoom(int obj) {
  477.     int i,cnt;
  478.     uint16 *ptr;
  479.     
  480.     for(i=1; i<=_numObjectsInRoom; i++) {
  481.         if (_objs[i].obj_nr==obj) {
  482.             if (_objs[i].numstrips != 0) {
  483.                 ptr = &actorDrawBits[_objs[i].x_pos];
  484.                 cnt = _objs[i].numstrips;
  485.                 do {
  486.                     *ptr++ |= 0x8000;
  487.                 } while (--cnt);
  488.             }
  489.             _BgNeedsRedraw = 1;
  490.             return;
  491.         }
  492.     }
  493. }
  494.  
  495. void Scumm::addObjectToDrawQue(int object) {
  496.     _drawObjectQue[_drawObjectQueNr++] = object;
  497.     if (_drawObjectQueNr > sizeof(_drawObjectQue)/sizeof(_drawObjectQue[0]))
  498.         error("Draw Object Que overflow");
  499. }
  500.  
  501. void Scumm::clearDrawObjectQueue() {
  502.     _drawObjectQueNr = 0;
  503. }
  504.  
  505. byte *Scumm::getObjOrActorName(int obj) {
  506.     byte *objptr;
  507.  
  508.     if (obj <= _vars[VAR_NUM_ACTOR])
  509.         return getActorName(derefActorSafe(obj, "getObjOrActorName"));
  510.  
  511.     objptr = getObjectAddress(obj);
  512.     if (objptr==NULL)
  513.         return (byte*)" ";
  514.     
  515.     return findResource(MKID('OBNA'), objptr, 0) + 8;
  516. }
  517.  
  518. uint32 Scumm::getOBCDOffs(int object) {
  519.     int i;
  520.  
  521.     if ((_objectFlagTable[object]&0xF)!=0xF)
  522.         return 0;
  523.     for (i=_numObjectsInRoom; i>0; i--) {
  524.         if (_objs[i].obj_nr == object) {
  525.             if (_objs[i].fl_object_index!=0)
  526.                 return 8;
  527.             return _objs[i].offs_obcd_to_room;
  528.         }
  529.     }
  530.     return 0;
  531. }
  532.  
  533. byte *Scumm::getObjectAddress(int obj) {
  534.     int i;
  535.  
  536.     if ((_objectFlagTable[obj]&0xF)!=0xF) {
  537.         for(i=0; i<_maxInventoryItems; i++) {
  538.             if (_inventory[i] == obj)
  539.                 return getResourceAddress(rtInventory, i);
  540.         }
  541.     } else {
  542.         for(i=_numObjectsInRoom; i>0; --i) {
  543.             if (_objs[i].obj_nr==obj) {
  544.                 if (_objs[i].fl_object_index)
  545.                     return getResourceAddress(rtFlObject, _objs[i].fl_object_index)+8;
  546.                 return getResourceAddress(rtRoom, _roomResource) + _objs[i].offs_obcd_to_room;
  547.             }
  548.         }
  549.     }
  550.     return 0;
  551. }
  552.  
  553. void Scumm::addObjectToInventory(uint obj, uint room) {
  554.     int i, slot;
  555.     byte *ptr,*obcdptr;
  556.     uint32 size,cdoffs;
  557.     int numobj;
  558.     byte *roomptr;
  559.     CodeHeader *cdhd;
  560.     RoomHeader *roomhdr;
  561.  
  562.     debug(1,"Adding object %d from room %d into inventory", obj, room);
  563.  
  564.     CHECK_HEAP
  565.  
  566.     if (whereIsObject(obj)==4) {
  567.         i = getObjectIndex(obj);
  568.         ptr = getResourceAddress(rtFlObject, _objs[i].fl_object_index) + 64;
  569.         size = READ_BE_UINT32_UNALIGNED(ptr+4);
  570.         slot = getInventorySlot();
  571.         _inventory[slot] = obj;
  572.         createResource(rtInventory, slot, size);
  573.         ptr = getResourceAddress(rtFlObject, _objs[i].fl_object_index) + 64;
  574.         memcpy(getResourceAddress(rtInventory, slot), ptr, size);
  575.         CHECK_HEAP
  576.         return;
  577.     }
  578. //    ensureResourceLoaded(rtRoom, room);
  579.     roomptr = getResourceAddress(rtRoom, room);
  580.     roomhdr = (RoomHeader*)findResource(MKID('RMHD'), roomptr, 0);
  581.     numobj = READ_LE_UINT16(&roomhdr->numObjects);
  582.     if (numobj==0)
  583.         error("addObjectToInventory: No object found in room %d", room);
  584.     if (numobj > _numLocalObjects)
  585.         error("addObjectToInventory: More (%d) than %d objects in room %d", numobj, _numLocalObjects, room);
  586.  
  587.     for (i=0; i<numobj; i++) {
  588.         obcdptr = findResource(MKID('OBCD'), roomptr, i);
  589.         if(obcdptr==NULL)
  590.             error("addObjectToInventory: Not enough code blocks in room %d", room);
  591.         cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcdptr, 0);
  592.         if ( READ_LE_UINT16(&cdhd->obj_id) == obj) {
  593.             cdoffs = obcdptr - roomptr;
  594.             size = READ_BE_UINT32_UNALIGNED(obcdptr+4);
  595.             slot = getInventorySlot();
  596.             _inventory[slot] = obj;
  597.             createResource(rtInventory, slot, size);
  598.             obcdptr = getResourceAddress(rtRoom, room) + cdoffs;
  599.             memcpy(getResourceAddress(rtInventory,slot),obcdptr,size);
  600.             CHECK_HEAP
  601.             return;
  602.         }
  603.     }
  604.  
  605.     error("addObjectToInventory: Object %d not found in room %d", obj, room);
  606. }
  607.  
  608. int Scumm::getInventorySlot() {
  609.     int i;
  610.     for (i=1; i<=_maxInventoryItems; i++) {
  611.         if (_inventory[i]==0)
  612.             return i;
  613.     }
  614.     error("Inventory full, %d max items", _maxInventoryItems);
  615. }
  616.  
  617. void Scumm::setOwnerOf(int obj, int owner) {
  618.     ScriptSlot *ss;
  619.     if (owner==0) {
  620.         clearOwnerOf(obj);
  621.         ss = &vm.slot[_currentScript];
  622.         if (ss->type==0 && _inventory[ss->number]==obj) {
  623.             putOwner(obj, 0);
  624.             runHook(0);
  625.             stopObjectCode();
  626.             return;
  627.         }
  628.     }
  629.     putOwner(obj, owner);
  630.     runHook(0);
  631. }
  632.  
  633. int Scumm::getObjX(int obj) {
  634.     if (obj <= _vars[VAR_NUM_ACTOR]) {
  635.         return derefActorSafe(obj,"getObjX")->x;
  636.     } else {
  637.         if (whereIsObject(obj)==-1)
  638.             return -1;
  639.         getObjectOrActorXY(obj);
  640.         return _xPos;
  641.     }
  642. }
  643.  
  644. int Scumm::getObjY(int obj) {
  645.     if (obj <= _vars[VAR_NUM_ACTOR]) {
  646.         return derefActorSafe(obj,"getObjY")->y;
  647.     } else {
  648.         if (whereIsObject(obj)==-1)
  649.             return -1;
  650.         getObjectOrActorXY(obj);
  651.         return _yPos;
  652.     }
  653. }
  654.  
  655. int Scumm::getObjDir(int obj) {
  656.     if (obj <= _vars[VAR_NUM_ACTOR]) {
  657.         return derefActorSafe(obj,"getObjDir")->facing;
  658.     } else {
  659.         getObjectXYPos(obj);
  660.         return _dir;
  661.     }
  662. }
  663.  
  664. int Scumm::findInventory(int owner, int index) {
  665.     int count = 1, i, obj;
  666.     for (i=0; i!=_maxInventoryItems; i++) {
  667.         obj = _inventory[i];
  668.         if (obj && getOwner(obj)==owner && count++ == index)
  669.             return obj;
  670.     }
  671.     return 0;    
  672. }
  673.  
  674. int Scumm::getInventoryCount(int owner) {
  675.     int i,obj;
  676.     int count = 0;
  677.     for (i=0; i!=_maxInventoryItems; i++) {
  678.         obj = _inventory[i];
  679.         if (obj && getOwner(obj) == owner)
  680.             count++;
  681.     }
  682.     return count;
  683. }
  684.  
  685. void Scumm::setObjectState(int obj, int state, int x, int y) {
  686.     int i;
  687.  
  688.     i = getObjectIndex(obj);
  689.     if (i==-1)
  690.         return;
  691.  
  692.     if (x != -1) {
  693.         _objs[i].x_pos = x;
  694.         _objs[i].y_pos = y;
  695.     }
  696.  
  697.     addObjectToDrawQue(i);
  698.     putState(obj, state);
  699. }
  700.  
  701. static int getDist(int x, int y, int x2, int y2) {
  702.     int a = abs(y-y2);
  703.     int b = abs(x-x2);
  704.     if (a>b)
  705.         return a;
  706.     return b;
  707. }
  708.  
  709. int Scumm::getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, int e, int f) {
  710.     int i,j;
  711.     int x,y;
  712.     int x2,y2;
  713.     
  714.     j = i = 0xFF;
  715.  
  716.     if (is_obj_1) {
  717.         if (getObjectOrActorXY(b)==-1)
  718.             return -1;
  719.         if (b < _vars[VAR_NUM_ACTOR])
  720.             i = derefActorSafe(b, "unkObjProc1")->scalex;
  721.         x = _xPos;
  722.         y = _yPos;
  723.     } else {
  724.         x = b;
  725.         y = c;
  726.     }
  727.  
  728.     if (is_obj_2) {
  729.         if (getObjectOrActorXY(e)==-1)
  730.             return -1;
  731.         if (e < _vars[VAR_NUM_ACTOR])
  732.             j = derefActorSafe(e, "unkObjProc1(2)")->scalex;
  733.         x2 = _xPos;
  734.         y2 = _yPos;
  735.     } else {
  736.         x2 = e;
  737.         y2 = f;
  738.     }
  739.  
  740.     return getDist(x,y,x2,y2) * 0xFF / ((i + j)>>1);
  741. }
  742.  
  743. void Scumm::setCursorImg(uint room, uint img) {
  744.     byte *ptr;
  745.     int index;
  746.     CodeHeader *cdhd;
  747.     ImageHeader *imhd;
  748.     int w,h;
  749.     byte *roomptr,*obcd,*obim,*dataptr,*bomp;
  750.     RoomHeader *rmhd;
  751.     int i,numobj;
  752.     uint32 size;
  753.  
  754.     if (getObjectIndex(img)!=-1) {
  755.         obim = getObjectAddress(img);
  756.         ptr = obim + READ_BE_UINT32(&((ImageHeader*)obim)->size);
  757.         cdhd = (CodeHeader*)findResource(MKID('CDHD'), obim, 0);
  758.         imhd = (ImageHeader*)findResource(MKID('IMHD'), ptr, 0);
  759.     } else {
  760.         ensureResourceLoaded(1, room);
  761.         roomptr = getResourceAddress(1, room);
  762.         rmhd = (RoomHeader*)findResource(MKID('RMHD'), roomptr, 0);
  763.  
  764.         numobj = READ_LE_UINT16(&rmhd->numObjects);
  765.         for(i=0; ;i++) {
  766.             if (i>=numobj)
  767.                 error("setCursorImg: object %d code not found in room %d", img, room);
  768.             
  769.             obcd = findResource(MKID('OBCD'), roomptr, i);
  770.             if (obcd==NULL)
  771.                 error("setCursorImg: not enough code blocks in room %d", room);
  772.             cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcd, 0);
  773.             if (READ_LE_UINT16(&cdhd->obj_id) == img)
  774.                 break;
  775.         }
  776.  
  777.         for(i=0; ;i++) {
  778.             if (i>=numobj)
  779.                 error("setCursorImg: object %d image not found in room %d", img, room);
  780.             obim = findResource(MKID('OBIM'), roomptr, i);
  781.             if (obim==NULL)
  782.                 error("setCursorImg: not enough image blocks in room %d", room);
  783.             imhd = (ImageHeader*)findResource(MKID('IMHD'), obim, 0);
  784.             if (READ_LE_UINT16(&imhd->obj_id) == img)
  785.                 break;
  786.         }
  787.     }
  788.  
  789.     setCursorHotspot2(
  790.         READ_LE_UINT16(&imhd->hotspot[0].x),
  791.         READ_LE_UINT16(&imhd->hotspot[0].y));
  792.  
  793.     w = READ_LE_UINT16(&cdhd->v6.w)>>3;
  794.     h = READ_LE_UINT16(&cdhd->v6.h)>>3;
  795.  
  796.     size = READ_BE_UINT32(&cdhd->size);
  797.     if (size > sizeof(_grabbedCursor))
  798.         error("setCursorImg: Cursor image too large");
  799.     
  800.     dataptr = findResource(MKID('IM01'),obim, 0);
  801.  
  802.     if ((bomp = findResource(MKID('BOMP'), dataptr, 0)) != NULL)
  803.         useBompCursor(bomp, w, h);
  804.     else
  805.         useIm01Cursor(dataptr, w, h);
  806.  
  807. }
  808.