diff options
-rw-r--r-- | actor.cpp | 143 | ||||
-rw-r--r-- | boxes.cpp | 329 | ||||
-rw-r--r-- | costume.cpp | 4 | ||||
-rw-r--r-- | resource.cpp | 11 | ||||
-rw-r--r-- | script_v1.cpp | 28 | ||||
-rw-r--r-- | scumm.h | 24 |
6 files changed, 381 insertions, 158 deletions
@@ -646,6 +646,9 @@ void Scumm::walkActors() { for (i=1; i<NUM_ACTORS; i++) { a = derefActor(i); if (a->room==_currentRoom) + if(_features & GF_OLD256) + walkActorOld(a); + else walkActor(a); } } @@ -753,6 +756,7 @@ void Scumm::walkActor(Actor *a) { } a->walkdata.curbox = j; + if (findPathTowards(a, a->walkbox, j, a->walkdata.destbox)) { a->moving |= 8; calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty); @@ -777,10 +781,33 @@ void Scumm::walkActor(Actor *a) { return; } a->walkdata.curbox = j; - if (findPathTowards(a, a->walkbox, j, a->walkdata.destbox)) - break; - if (calcMovementFactor(a, _foundPathX, _foundPathY)) - return; + if(_features & GF_OLD256) + { + findPathTowardsOld(a, a->walkbox, j, a->walkdata.destbox); + if (p[2].x == 32000 && p[3].x == 32000) + { + a->moving |= 8; + calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty); + return; + } + + if (p[2].x != 32000) { + if (calcMovementFactor(a, p[2].x, p[2].y)){ + a->walkdata.destx = p[3].x; + a->walkdata.desty = p[3].y; + return; + } + } + + if (calcMovementFactor(a, p[3].x, p[3].y)) + return; + + } else { + if (findPathTowards(a, a->walkbox, j, a->walkdata.destbox)) + break; + if (calcMovementFactor(a, _foundPathX, _foundPathY)) + return; + } setActorBox(a, a->walkdata.curbox); } while (1); @@ -1078,6 +1105,8 @@ void Scumm::startWalkActor(Actor *a, int x, int y, int dir) { a->walkdata.destbox = (byte)abr.dist; /* a box */ a->walkdata.destdir = dir; a->moving = (a->moving&2)|1; + a->walkdata.point3x = 32000; + a->walkdata.curbox = a->walkbox; } @@ -1180,3 +1209,109 @@ void Scumm::setupShadowPalette(int slot,int rfact,int gfact,int bfact,int from,i curpal+=3; } while (--num); } + +void Scumm::walkActorOld(Actor *a) { + int new_dir,next_box,goto_x,goto_y; + + if(!a->moving) + return; + + if(a->moving&1) + { +restart: + a->moving &= ~1; + + if (a->walkbox==0xFF) + { + a->walkbox = a->walkdata.destbox; + a->walkdata.curbox = a->walkdata.destbox; + a->moving |=8; + calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty); + return; + } + + if (a->walkbox==a->walkdata.destbox) + { + a->moving |=8; + calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty); + return; + } + + next_box = getPathToDestBox(a->walkbox,a->walkdata.destbox); + + if( next_box == -1) + { + a->moving |=8; + return; + } + + a->walkdata.curbox = next_box; + + findPathTowardsOld(a, a->walkbox, next_box, a->walkdata.destbox); + if(p[2].x == 32000 && p[3].x == 32000) + { + a->moving |=8; + calcMovementFactor(a, a->walkdata.destx, a->walkdata.desty); + return; + } + + if(p[2].x != 32000) + { + if(calcMovementFactor(a, p[2].x, p[2].y)) + { + actor->walkdata.point3x=p[3].x; + actor->walkdata.point3y=p[3].y; + return; + } + } + + if(calcMovementFactor(a,p[3].x,p[3].y)) + return; + + a->walkbox = a->walkdata.destbox; + a->mask = getMaskFromBox(a->walkbox); + goto restart; + + } + + if(a->moving & 2) + { + if(actorWalkStep(a)) + return; + } + + if(a->moving & 8) + { + a->moving = 0; + startWalkAnim(a, 3, a->walkdata.destdir); + return; + } + + if(a->moving & 4) + { + new_dir = updateActorDirection(a); + if (a->facing != new_dir) + { + fixActorDirection(a,new_dir); + return; + } + a->moving=0; + return; + } + + if(a->walkdata.point3x != 32000) + { + if(calcMovementFactor(a,a->walkdata.point3x,a->walkdata.point3y)) + { + a->walkdata.point3x=32000; + return; + } + a->walkdata.point3x=32000; + } + + a->walkbox = a->walkdata.curbox; + a->mask = getMaskFromBox(a->walkbox); + a->moving &= 2; + a->moving |= 1; +goto restart; +} @@ -21,6 +21,7 @@ #include "stdafx.h" #include "scumm.h" +#include "math.h" byte Scumm::getMaskFromBox(int box) { Box *ptr = getBoxBaseAddr(box); @@ -121,10 +122,22 @@ void Scumm::getBoxCoordinates(int boxnum, BoxCoords *box) { box->ul.y = (int16)FROM_LE_16(bp->uly); box->ur.x = (int16)FROM_LE_16(bp->urx); box->ur.y = (int16)FROM_LE_16(bp->ury); - box->ll.x = (int16)FROM_LE_16(bp->llx); - box->ll.y = (int16)FROM_LE_16(bp->lly); - box->lr.x = (int16)FROM_LE_16(bp->lrx); - box->lr.y = (int16)FROM_LE_16(bp->lry); + + if(_features & GF_OLD256) + { + box->ll.x = (int16)FROM_LE_16(bp->lrx); + box->ll.y = (int16)FROM_LE_16(bp->lry); + box->lr.x = (int16)FROM_LE_16(bp->llx); + box->lr.y = (int16)FROM_LE_16(bp->lly); + } + else + { + box->ll.x = (int16)FROM_LE_16(bp->llx); + box->ll.y = (int16)FROM_LE_16(bp->lly); + box->lr.x = (int16)FROM_LE_16(bp->lrx); + box->lr.y = (int16)FROM_LE_16(bp->lry); + } + } uint Scumm::distanceFromPt(int x, int y, int ptx, int pty) { @@ -465,8 +478,6 @@ int Scumm::findPathTowards(Actor *a, byte box1nr, byte box2nr, byte box3nr) { box2.ll = box2.lr; box2.lr = tmp; } - warning("findPathTowards: default"); // FIXME: ZAK256 - findPathTowardsOld(a, box1nr, box2nr, box3nr); return 0; } void Scumm::setBoxFlags(int box, int val) { @@ -804,149 +815,181 @@ void *Scumm::addToBoxVertexHeap(int size) { PathVertex *Scumm::addPathVertex() { _boxMatrixPtr4 = getResourceAddress(rtMatrix, 4); _boxPathVertexHeapIndex = 0; + return (PathVertex*)addToBoxVertexHeap(sizeof(PathVertex)); } -int Scumm::findPathTowardsOld(Actor *a, byte box1nr, byte box2nr, byte box3nr) { - BoxCoords box1; - BoxCoords box2; - ScummPoint tmp; - int i,j; - int flag; - int q,pos; - int threshold=1; - - getBoxCoordinates(box1nr,&box1); - getBoxCoordinates(box2nr,&box2); - - do{ - for(i=0; i<4; i++) { - for(j=0; j<4; j++) { - if (abs(box1.ul.x-box1.ur.x)<threshold && - abs(box1.ul.x-box2.ul.x)<threshold && - abs(box1.ul.x-box2.ur.x)<threshold ) { - flag = 0; - if (box1.ul.y > box1.ur.y) { - SWAP(box1.ul.y, box1.ur.y); - flag |= 1; - } - - if (box2.ul.y > box2.ur.y) { - SWAP(box2.ul.y, box2.ur.y); - flag |= 2; - } - - if (box1.ul.y > box2.ur.y || box2.ul.y > box1.ur.y || - (box1.ur.y==box2.ul.y || box2.ur.y==box1.ul.y) && - box1.ul.y!=box1.ur.y && box2.ul.y!=box2.ur.y) { - if (flag&1) - SWAP(box1.ul.y, box1.ur.y); - if (flag&2) - SWAP(box2.ul.y, box2.ur.y); - } else { - if (box2nr == box3nr) { - int diffX = a->walkdata.destx - a->x; - int diffY = a->walkdata.desty - a->y; - int boxDiffX = box1.ul.x - a->x; - - if (diffX!=0) { - int t; - - diffY *= boxDiffX; - t = diffY / diffX; - if (t==0 && (diffY<=0 || diffX<=0) && (diffY>=0 || diffX>=0)) - t = -1; - pos = a->y + t; - } else { - pos = a->y; - } - } else { - pos = a->y; - } - - q = pos; - if (q < box2.ul.y) - q = box2.ul.y; - if (q > box2.ur.y) - q = box2.ur.y; - if (q < box1.ul.y) - q = box1.ul.y; - if (q > box1.ur.y) - q = box1.ur.y; - if (q==pos && box2nr==box3nr) - return 1; - _foundPathY = q; - _foundPathX = box1.ul.x; - return 0; - } - } +int Scumm::findPathTowardsOld(Actor *a, byte trap1, byte trap2, byte final_trap) +{ + GetGates(trap1,trap2); + ScummPoint pt; - if (abs(box1.ul.y-box1.ur.y)<threshold && - abs(box1.ul.y-box2.ul.y)<threshold && - abs(box1.ul.y-box2.ur.y)<threshold ){ - flag = 0; - if (box1.ul.x > box1.ur.x) { - SWAP(box1.ul.x, box1.ur.x); - flag |= 1; - } - - if (box2.ul.x > box2.ur.x) { - SWAP(box2.ul.x, box2.ur.x); - flag |= 2; - } - - if (box1.ul.x > box2.ur.x || box2.ul.x > box1.ur.x || - (box1.ur.x==box2.ul.x || box2.ur.x==box1.ul.x) && - box1.ul.x!=box1.ur.x && box2.ul.x!=box2.ur.x) { - if (flag&1) - SWAP(box1.ul.x, box1.ur.x); - if (flag&2) - SWAP(box2.ul.x, box2.ur.x); - } else { - - if (box2nr == box3nr) { - int diffX = a->walkdata.destx - a->x; - int diffY = a->walkdata.desty - a->y; - int boxDiffY = box1.ul.y - a->y; - - pos = a->x; - if (diffY!=0) { - pos += diffX * boxDiffY / diffY; - } - } else { - pos = a->x; - } - - q = pos; - if (q < box2.ul.x) - q = box2.ul.x; - if (q > box2.ur.x) - q = box2.ur.x; - if (q < box1.ul.x) - q = box1.ul.x; - if (q > box1.ur.x) - q = box1.ur.x; - if (q==pos && box2nr==box3nr) - return 1; - _foundPathX = q; - _foundPathY = box1.ul.y; - return 0; - } + p[1].x = actor->x; + p[1].y = actor->y; + p[2].x = 32000; + p[3].x = 32000; + p[4].x = 32000; + + if (trap2 == final_trap) { /* next = final box? */ + p[4].x = actor->walkdata.destx; + p[4].y = actor->walkdata.desty; + + if (getMaskFromBox(trap1) == getMaskFromBox(trap2) || 1) { + if (CompareSlope(p[1].x,p[1].y,p[4].x,p[4].y, gate1ax,gate1ay) != + CompareSlope(p[1].x,p[1].y,p[4].x,p[4].y, gate1bx,gate1by) && + CompareSlope(p[1].x,p[1].y,p[4].x,p[4].y, gate2ax,gate2ay) != + CompareSlope(p[1].x,p[1].y,p[4].x,p[4].y, gate2bx,gate2by)) { + return 0; /* same zplane and between both gates? */ } - tmp = box1.ul; - box1.ul = box1.ur; - box1.ur = box1.ll; - box1.ll = box1.lr; - box1.lr = tmp; } - tmp = box2.ul; - box2.ul = box2.ur; - box2.ur = box2.ll; - box2.ll = box2.lr; - box2.lr = tmp; } - threshold++; - }while(threshold<10); - error("findPathTowardsOld: default"); // FIXME: ZAK256 + + pt=closestPtOnLine(gate2ax,gate2ay,gate2bx,gate2by,p[1].x,p[1].y); + p[3].x = pt.x; + p[3].y = pt.y; + + if (CompareSlope(p[1].x,p[1].y,p[3].x,p[3].y, gate1ax,gate1ay) == + CompareSlope(p[1].x,p[1].y,p[3].x,p[3].y, gate1bx,gate1by)) { + closestPtOnLine(gate1ax,gate1ay,gate1bx,gate1by,p[1].x,p[1].y); + p[2].x = pt.x; /* if point 2 between gates, ignore! */ + p[2].y = pt.y; + } + return 0; } + +void Scumm::GetGates(int trap1,int trap2) { +int i; +int Closest1,Closest2,Closest3; +int Dist[8]; +int Dist1,Dist2,Dist3; +int Box1,Box2,Box3; +BoxCoords box; +int polyx[8]; +int polyy[8]; +AdjustBoxResult pt; + + getBoxCoordinates(trap1,&box); + polyx[0] = box.ul.x; + polyy[0] = box.ul.y; + polyx[1] = box.ur.x; + polyy[1] = box.ur.y; + polyx[2] = box.ll.x; + polyy[2] = box.ll.y; + polyx[3] = box.lr.x; + polyy[3] = box.lr.y; + for (i = 0 ; i < 4 ; i++) { + pt = getClosestPtOnBox(trap2,polyx[i],polyy[i]); + Dist[i] = pt.dist; + CloX[i] = pt.x; + CloY[i] = pt.y; + } + + getBoxCoordinates(trap2,&box); + polyx[4] = box.ul.x; + polyy[4] = box.ul.y; + polyx[5] = box.ur.x; + polyy[5] = box.ur.y; + polyx[6] = box.ll.x; + polyy[6] = box.ll.y; + polyx[7] = box.lr.x; + polyy[7] = box.lr.y; + for (i = 4 ; i < 8 ; i++) { + pt = getClosestPtOnBox(trap1,polyx[i],polyy[i]); + Dist[i] = pt.dist; + CloX[i] = pt.x; + CloY[i] = pt.y; + } + + + Dist1 = 0xFFFF; + for (i = 0 ; i < 8 ; i++) { + if (Dist[i] < Dist1) { + Dist1 = Dist[i]; + Closest1 = i; + } + } + Dist[Closest1] = 0xFFFF; + + Dist2 = 0xFFFF; + for (i = 0 ; i < 8 ; i++) { + if (Dist[i] < Dist2) { + Dist2 = Dist[i]; + Closest2 = i; + } + } + Dist[Closest2] = 0xFFFF; + + Dist3 = 0xFFFF; + for (i = 0 ; i < 8 ; i++) { + if (Dist[i] < Dist3) { + Dist3 = Dist[i]; + Closest3 = i; + } + } + + Box1 = (Closest1 > 3); + Box2 = (Closest2 > 3); + Box3 = (Closest3 > 3); + + Dist1 = (int)sqrt(Dist1); + Dist2 = (int)sqrt(Dist2); + Dist3 = (int)sqrt(Dist3); + + if (Box1 == Box2 && abs(Dist1-Dist2) < 4) { + SetGate(Closest1,Closest2,polyx,polyy); + + } else if (Box1 == Box2 && Dist1 == Dist2) { /* parallel */ + SetGate(Closest1,Closest2,polyx,polyy); + } else if (Box1 == Box3 && Dist1 == Dist3) { /* parallel */ + SetGate(Closest1,Closest3,polyx,polyy); + } else if (Box2 == Box3 && Dist2 == Dist3) { /* parallel */ + SetGate(Closest2,Closest3,polyx,polyy); + + + } else if (Box1 == Box3 && abs(Dist1-Dist3) < 4) { + SetGate(Closest1,Closest3,polyx,polyy); + } else if (abs(Dist1-Dist3) < 4) { /* if 1 close to 3 then use 2-3 */ + SetGate(Closest2,Closest3,polyx,polyy); + } else if (abs(Dist1-Dist2) < 4) { + SetGate(Closest1,Closest2,polyx,polyy); + } else { + SetGate(Closest1,Closest1,polyx,polyy); + } +} + +int Scumm::CompareSlope(int X1,int Y1,int X2,int Y2,int X3,int Y3) +{ + if ((Y2 - Y1) * (X3 - X1) > (Y3 - Y1) * (X2 - X1)) return(0); + return(1); +} + +void Scumm::SetGate(int line1,int line2, int polyx[8], int polyy[8]) +{ + + if (line1 < 4) { /* from box 1 to box 2 */ + gate1ax = polyx[line1]; + gate1ay = polyy[line1]; + gate2ax = CloX[line1]; + gate2ay = CloY[line1]; + + } else { + gate2ax = polyx[line1]; + gate2ay = polyy[line1]; + gate1ax = CloX[line1]; + gate1ay = CloY[line1]; + } + + if (line2 < 4) { /* from box */ + gate1bx = polyx[line2]; + gate1by = polyy[line2]; + gate2bx = CloX[line2]; + gate2by = CloY[line2]; + + } else { + gate2bx = polyx[line2]; + gate2by = polyy[line2]; + gate1bx = CloX[line2]; + gate1by = CloY[line2]; + } +} diff --git a/costume.cpp b/costume.cpp index ebd32a499c..80a8e3763c 100644 --- a/costume.cpp +++ b/costume.cpp @@ -727,8 +727,8 @@ byte CostumeRenderer::drawOneSlot(Actor *a, int slot) { _srcptr = _loaded._ptr + READ_LE_UINT16(_frameptr + code*2); if (code != 0x7B) { - if ( !(_vm->_features & GF_OLD256) || code <0x79) - return mainRoutine(a, slot, code); + if(_vm->_features & GF_OLD256 && code < 0x78) + return mainRoutine(a, slot, code); } } diff --git a/resource.cpp b/resource.cpp index 26e13ab14e..6f8c22303b 100644 --- a/resource.cpp +++ b/resource.cpp @@ -326,6 +326,7 @@ void Scumm::readIndexFileSmall() { uint32 itemsize; int numblock = 0; int num, i; + byte* _oldClass; debug(9, "readIndexFile()"); @@ -420,10 +421,12 @@ void Scumm::readIndexFileSmall() { num = fileReadWordLE(); assert(num == _numGlobalObjects); for (i=0; i<num; i++) { /* not too sure about all that */ - _classData[i] = fileReadByte() + 256*fileReadByte()+ 256*256*fileReadByte(); - // fileReadByte(); - _objectOwnerTable[i] = fileReadByte(); - _objectStateTable[i] = _objectOwnerTable[i]>>OF_STATE_SHL; + _oldClass=(byte*)&_classData[i]; + _oldClass[0]=fileReadByte(); + _oldClass[1]=fileReadByte(); + _oldClass[2]=fileReadByte(); + _objectOwnerTable[i] = fileReadByte(); + // _objectStateTable[i] = fileReadByte(); _objectOwnerTable[i] &= OF_OWNER_MASK; } diff --git a/script_v1.cpp b/script_v1.cpp index 9e4f7c11ec..904f02777e 100644 --- a/script_v1.cpp +++ b/script_v1.cpp @@ -804,9 +804,14 @@ FixRoom: } } +const short int bit_table[16] = +{1,2,4,8,0x10,0x20,0x40,0x80,0x100,0x200,0x400,0x800,0x1000,0x2000,0x4000,0x8000}; + + void Scumm::o5_actorSetClass() { int act = getVarOrDirectWord(0x80); int newClass; + byte *oldClassData; while ( (_opcode=fetchScriptByte()) != 0xFF) { newClass = getVarOrDirectWord(0x80); @@ -814,10 +819,18 @@ void Scumm::o5_actorSetClass() { _classData[act] = 0; continue; } - if (newClass&0x80) - putClass(act, newClass, 1); - else - putClass(act, newClass, 0); + if(_features & GF_SMALL_HEADER) { + oldClassData=(byte*)&_classData[act]; + if (newClass&0x80) + oldClassData[((newClass-1)&0x7f)/8] |= bit_table[((newClass-1)&0x07)]; + else + oldClassData[((newClass-1)&0x7f)/8] &= bit_table[((newClass-1)&0x07)]^0xff; + } else { + if (newClass&0x80) + putClass(act, newClass, 1); + else + putClass(act, newClass, 0); + } } } @@ -1331,11 +1344,16 @@ void Scumm::o5_getVerbEntrypoint() { void Scumm::o5_ifClassOfIs() { int act,cls; bool cond = true, b; + byte *oldClass; act = getVarOrDirectWord(0x80); while ( (_opcode = fetchScriptByte()) != 0xFF) { cls = getVarOrDirectWord(0x80); - b = getClass(act, cls); + oldClass = (byte*)&_classData[act]; + if(_features & GF_SMALL_HEADER) + b = oldClass[((cls-1)&0x7f)/8] & bit_table[((cls-1)&0x07)]; + else + b = getClass(act, cls); if (cls&0x80 && !b || !(cls&0x80) && b) cond = false; @@ -37,6 +37,12 @@ struct Scumm; struct Actor; +struct gate_location +{ + int x; + int y; +}; + #include "smush.h" typedef void (Scumm::*OpcodeProc)(); @@ -329,6 +335,7 @@ struct ActorWalkData { int16 x,y,newx,newy; int32 XYFactor, YXFactor; uint16 xfrac,yfrac; + int point3x, point3y; }; struct MouseCursor { @@ -2155,6 +2162,8 @@ struct Scumm { byte VAR_UNK_SCRIPT; byte VAR_UNK_SCRIPT_2; + + void GetGates(int trap1,int trap2); byte VAR_DEFAULT_TALK_DELAY; byte VAR_CHARSET_MASK; @@ -2162,6 +2171,21 @@ struct Scumm { int NUM_ACTORS; byte _videoPath[50]; + + gate_location p[5]; + + int CompareSlope(int X1,int Y1,int X2,int Y2,int X3,int Y3); + void SetGate(int line1,int line2, int polyx[8], int polyy[8]); + + int gate1ax, gate1ay; + int gate1bx, gate1by; + int gate2ax, gate2ay; + int gate2bx, gate2by; + + int CloX[8]; + int CloY[8]; + + void walkActorOld(Actor *a); }; enum AkosOpcodes{ |