Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //NK_PHYS.C
- #include "NK_DEF.H"
- //Does all the tileclipping, general movement
- // contains some generic sprite collision and draw funcs
- // This is reversed directly from Keen5
- // Tile (T) = 16 Pixels (Px) = 256 Map Units (MU)
- //===========================================================================
- int SlopeDisp[8][16] =
- {
- { 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100 },
- { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
- { 0x0, 0x8, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 },
- { 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8 },
- { 0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 },
- { 0x78, 0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08, 0x0 },
- { 0xF8, 0xF0, 0xE8, 0xE0, 0xD8, 0xD0, 0xC8, 0xC0, 0xB8, 0xB0, 0xA8, 0xA0, 0x98, 0x90, 0x88, 0x80 },
- { 0xF0, 0xE0, 0xD0, 0xC0, 0xB0, 0xA0, 0x90, 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x0 }
- };
- Vectrect KeenClip;
- int KeenClipXMid;
- Rect KeenBox;
- unsigned KeenBoxXMid;
- Rect KeenBoxT;
- unsigned KeenBoxTXMid;
- Vector KeenVel;
- int KeenPushedHorz;
- void UpdateYPos(objtype *o, int dy);
- void UpdateXPos(objtype *o, int dx);
- void MoveDown(objtype *o);
- void MoveUp(objtype *o);
- void SetOnSlope(objtype *o);
- void MoveOutOfTileHorz(objtype *o);
- int CheckIfStuck(objtype *o);
- void UpdateHitbox(objtype *o);
- void NormalClip(objtype *o);
- void FullClipToWalls(objtype *o);
- void SimpleClip(objtype *o);
- void PushHorz(objtype *o1, objtype *o2);
- void PushVert(objtype *o1, objtype *o2);
- int TimeAction(objtype *o, int time);
- void DoAction(objtype *o);
- void CheckGround(objtype *o, ACTION *a);
- void CheckGround2(objtype *o, ACTION *a);
- boolean ObjectVisible(objtype *o);
- //===========================================================================
- /*
- ============================
- =
- = UpdateYPos, UpdateXPos
- =
- = Move object by dy, dx MU
- =
- ============================
- */
- // rechecked -- perfect
- void UpdateYPos(objtype *o, int dy)
- {
- o->pos.y += dy;
- o->box.ul.y += dy;
- o->box.lr.y += dy;
- o->boxT.ul.y = MU2TILE(o->box.ul.y);
- o->boxT.lr.y = MU2TILE(o->box.lr.y);
- }
- // rechecked -- perfect
- void UpdateXPos(objtype *o, int dx)
- {
- o->pos.x += dx;
- o->box.ul.x += dx;
- o->box.lr.x += dx;
- o->boxT.ul.x = MU2TILE(o->box.ul.x);
- o->boxT.lr.x = MU2TILE(o->box.lr.x);
- }
- /*
- ============================
- =
- = MoveDown / MoveUp
- =
- = Move object down/up and check sloped tile collisions
- = We have just moved across tileboundaries (likely)
- =
- ============================
- */
- // rechecked -- perfect
- // Moving across boundaries as per the situation described in "NormalClip"
- void MoveDown(objtype *o)
- {
- int dx, dy, x_px, slope, topflag; // change in MU, tile PX
- int far *tile;
- // Get fgtile one above the new bottom;
- // no move if wall left at tile or tile-1
- tile = (int far *)MAPSPOT_FP(0,o->boxT.lr.y-1,FGPLANE);
- // Check if object is running into a wall above the tile we came from
- // If so, then don't move it up.
- if (o->xmotion == motion_Right)
- {
- //move right
- x_px = 0;
- tile += o->boxT.lr.x;
- dx = o->box.lr.x - o->boxXmid;
- if (TI_FGLeft(*(tile-map_width_T)) || TI_FGLeft(*tile))
- return;
- }
- else
- {
- //do left
- x_px = 15;
- tile += o->boxT.ul.x;
- dx = o->box.ul.x - o->boxXmid;
- if (TI_FGRight(*(tile-map_width_T)) || TI_FGRight(*tile))
- return;
- }
- if (TI_FGTop(*tile))
- return;
- topflag = TI_FGTop(*(tile+=map_width_T));
- // move the object horizontally, and place it above the slope
- if (topflag == TF_FLAT)
- {
- slope = SlopeDisp[(topflag & 7)][x_px];
- dy = TILE2MU(o->boxT.lr.y) + slope - 1 - o->box.lr.y;
- if (dy <= 0 && -KeenClip.lr.y <= dy)
- {
- o->topflags = topflag;
- UpdateYPos(o, dy);
- UpdateXPos(o, dx);
- }
- }
- }
- // rechecked -- perfect
- void MoveUp(objtype *o)
- {
- int dy, x_px, slope, botflag; // change in MU, tile PX
- int far *tile;
- // Get fgtile one below ul; no move if wall left at tile or tile-1
- tile = (int far *)MAPSPOT_FP(0,o->boxT.ul.y+1,FGPLANE);
- if (o->xmotion == motion_Right)
- {
- //move Right
- x_px = 0;
- tile += o->boxT.lr.x;
- if (TI_FGLeft(*(tile+map_width_T)) || TI_FGLeft(*(tile+2*map_width_T)))
- return;
- }
- else
- {
- //move Left
- x_px = 15;
- tile += o->boxT.ul.x;
- if (TI_FGRight(*(tile+map_width_T)) || TI_FGRight(*(tile+2*map_width_T)))
- return;
- }
- if (TI_FGBot(*tile))
- return;
- botflag = TI_FGBot(*(tile-=map_width_T));
- if (botflag)
- {
- slope = SlopeDisp[botflag & 7][x_px];
- dy = TILE2MU(o->boxT.ul.y+1) - slope - o->box.ul.y;
- if (dy >= 0 && -KeenClip.ul.y >= dy)
- {
- o->botflags = botflag;
- UpdateYPos(o, dy);
- }
- }
- }
- // move the object VERTICALLY on top of top slope or under bottom slope
- // rechecked -- perfect
- void SetOnSlope(objtype *o)
- {
- int dy, varE, slope, flag, i;
- unsigned x_px;
- int far *t;
- // x_px = distance in px from left edge of tile of midpoint
- x_px = (o->boxXmid & 0xF0) >> 4;
- /* Set one pixel atop sloped floor */
- // varE = horz + vert distance moved this frame plus one pixel
- varE = -ABS(KeenClipXMid) - KeenClip.lr.y - 16;
- t = (int far *)MAPSPOT_FP(o->boxTXmid, KeenBoxT.lr.y-1, FGPLANE);
- /* Check the tile above the midpoint and on the new midpoint */
- for (i = KeenBoxT.lr.y-1; o->boxT.lr.y >= i; i++, t += map_width_T)
- {
- flag = TI_FGTop(*t);
- // ignore empty tiles
- if (flag == TF_NOT)
- continue;
- // get the y pixel displacement at the new midopint
- slope = SlopeDisp[flag&7][x_px];
- // dy is distance needed to get out from under slope at new midpoint
- dy = TILE2MU(i) + slope - 1 - o->box.lr.y;
- // if dy is up, AND the x distance covered (PLUS one pixel)
- // is greater than y-delta between dest y and hitbox start, then move up
- if (dy < 0 && dy >= varE)
- {
- o->topflags = flag;
- UpdateYPos(o, dy);
- return;
- }
- }
- /* Set under sloped ceiling */
- varE = ABS(KeenClipXMid) - KeenClip.ul.y + 16;
- t = (int far *)MAPSPOT_FP(o->boxTXmid, KeenBoxT.ul.y+1, FGPLANE);
- for (i = KeenBoxT.ul.y+1; o->boxT.ul.y <= i; i--, t-= map_width_T)
- {
- flag = TI_FGBot(*t);
- if (flag == BF_NOT)
- continue;
- slope = SlopeDisp[flag&7][x_px];
- dy = TILE2MU(i+1) - slope - o->box.ul.y;
- if (dy > 0 && dy <= varE && (KeenVel.y + dy < 0x100) &&
- (KeenVel.y + dy > -0x100))
- {
- o->botflags = flag;
- UpdateYPos(o, dy);
- }
- }
- }
- // if horz edges of object inside a blocking tile, move outisde
- // rechecked -- perfect
- void MoveOutOfTileHorz(objtype *o)
- {
- int far *t;
- int y0, y1, ty;
- y0 = o->boxT.ul.y;
- if (o->botflags > BF_FLAT)
- y0++;
- y1 = o->boxT.lr.y;
- if (o->topflags > TF_FLAT)
- y1--;
- for (ty = y0; ty <= y1; ty++)
- {
- t = (int far *)MAPSPOT_FP(o->boxT.ul.x, ty, FGPLANE);
- o->rightflags = TI_FGRight(*t);
- if (o->rightflags)
- {
- UpdateXPos(o, TILE2MU(o->boxT.ul.x+1) - o->box.ul.x);
- return;
- }
- }
- for (ty = y0; ty <= y1; ty++)
- {
- t = (int far *)MAPSPOT_FP(o->boxT.lr.x, ty, FGPLANE);
- o->leftflags = TI_FGLeft(*t);
- if (o->leftflags)
- {
- UpdateXPos(o, TILE2MU(o->boxT.lr.x) - 1 - o->box.lr.x);
- return;
- }
- }
- }
- /* Checks if object is stuck in a wall */
- int CheckIfStuck(objtype *o)
- {
- int nextrowdist, tx, ty;
- int far *t;
- t = (int far *)MAPSPOT_FP(o->boxT.ul.x, o->boxT.ul.y, FGPLANE);
- nextrowdist = map_width_T - (o->boxT.lr.x - o->boxT.ul.x + 1);
- for (ty = o->boxT.ul.y; ty <= o->boxT.lr.y; ty++)
- {
- for(tx = o->boxT.ul.x; tx <= o->boxT.lr.x; tx++)
- {
- if (TI_FGTop(*t) || TI_FGBot(*t) || TI_FGLeft(*t) || TI_FGRight(*t))
- return 0;
- t++;
- }
- t+=nextrowdist;
- }
- return 1;
- }
- // no xrefs here; skipping for nwo
- #if 00
- sub_196B3(objtype *o, int arg2) {
- if (o->xmotion > motion_None)
- {
- ... looks like changing a object chunk?
- arg2 is some sort of struct*?
- }
- #endif
- void UpdateHitbox(objtype *o)
- {
- spritetabletype far *sprhead_p;
- sprhead_p = spritetable + o->chunk-STARTSPRITES;
- o->box.ul.x = o->pos.x + sprhead_p->xl;
- o->box.lr.x = o->pos.x + sprhead_p->xh;
- o->box.ul.y = o->pos.y + sprhead_p->yl;
- o->box.lr.y = o->pos.y + sprhead_p->yh;
- o->boxXmid = (o->box.lr.x-o->box.ul.x)/2 + o->box.ul.x;
- }
- // rechecked 2x -- good
- void NormalClip(objtype *o)
- {
- unsigned xpos_0, ypos_0;
- boolean notonplatform;
- spritetabletype far *sprhead_p;
- xpos_0 = o->pos.x;
- ypos_0 = o->pos.y;
- notonplatform = false;
- /* Stick to slopes */
- if (o->action->change_v)
- {
- if (o->topflags == TF_PLATFORM)
- {
- KeenVel.y = 145;
- }
- else
- {
- if (KeenVel.x > 0)
- KeenVel.y = KeenVel.x + 16;
- else
- KeenVel.y = -KeenVel.x + 16;
- notonplatform = true;
- }
- }
- /* Set Max Vel */
- if (KeenVel.x > 239)
- KeenVel.x = 239;
- else if (KeenVel.x < -239)
- KeenVel.x = -239;
- if (KeenVel.y > 255)
- KeenVel.y = 255;
- else if (KeenVel.y < -239)
- KeenVel.y = -239;
- o->pos.x += KeenVel.x;
- o->pos.y += KeenVel.y;
- o->draw = true;
- if (o->chunk)
- {
- /* Set the temp box coords */
- sprhead_p = spritetable + (o->chunk - STARTSPRITES);
- KeenBoxT.ul.x = o->boxT.ul.x;
- KeenBoxT.lr.x = o->boxT.lr.x;
- KeenBoxT.ul.y = o->boxT.ul.y;
- KeenBoxT.lr.y = o->boxT.lr.y;
- KeenBoxTXMid = o->boxTXmid;
- KeenBox.ul.x = o->box.ul.x;
- KeenBox.lr.x = o->box.lr.x;
- KeenBox.ul.y = o->box.ul.y;
- KeenBox.lr.y = o->box.lr.y;
- KeenBoxXMid = o->boxXmid;
- /* Update object box using spritehead */
- o->box.ul.x = o->pos.x + sprhead_p->xl;
- o->box.lr.x = o->pos.x + sprhead_p->xh;
- o->box.ul.y = o->pos.y + sprhead_p->yl;
- o->box.lr.y = o->pos.y + sprhead_p->yh;
- o->boxXmid = (o->box.lr.x-o->box.ul.x)/2 + o->box.ul.x;
- o->boxT.ul.x = MU2TILE(o->box.ul.x);
- o->boxT.lr.x = MU2TILE(o->box.lr.x);
- o->boxT.ul.y = MU2TILE(o->box.ul.y);
- o->boxT.lr.y = MU2TILE(o->box.lr.y);
- o->boxTXmid = MU2TILE(o->boxXmid);
- /* Do Sloped Tile Checking */
- o->leftflags = o->botflags = o->rightflags = o->topflags = 0;
- if (o->clipping)
- {
- // KeenClip is frame delta for object box coordinates
- KeenClip.ul.x = o->box.ul.x - KeenBox.ul.x;
- KeenClip.lr.x = o->box.lr.x - KeenBox.lr.x;
- KeenClip.ul.y = o->box.ul.y - KeenBox.ul.y;
- KeenClip.lr.y = o->box.lr.y - KeenBox.lr.y;
- KeenClipXMid = o->boxXmid - KeenBoxXMid;
- // Try to set on or under a slope, but...
- SetOnSlope(o);
- // ... If the necessary delta in y position from start to atop/under slope
- // is more than the (x-delta + one pixel), then no movement is made
- // and the top/bottom flags are not set
- // This situation could occur when running along a flat surface
- // and coming into a discontinuous increase in the top of the surface
- // _______
- // T0 T1
- //
- // o--> e.g., approaching slope top,
- // _______ object o runs from t0 to t1
- // / don't want to "jump up" to the next surface
- // /
- if (o->type == obj_keen && KeenPushedHorz == 0)
- {
- // So now handle this situation
- if (!o->topflags && KeenClip.lr.y > 0)
- MoveDown(o);
- if (!o->botflags && KeenClip.ul.y < 0)
- MoveUp(o);
- }
- MoveOutOfTileHorz(o);
- }
- /* Not On Platform and Falling */
- if (notonplatform && !o->topflags)
- {
- o->pos.y = ypos_0;
- o->pos.x = xpos_0 + KeenVel.x;
- o->box.ul.x = o->pos.x + sprhead_p->xl;
- o->box.lr.x = o->pos.x + sprhead_p->xh;
- o->box.ul.y = o->pos.y + sprhead_p->yl;
- o->box.lr.y = o->pos.y + sprhead_p->yh;
- o->boxXmid = (o->box.lr.x-o->box.ul.x)/2 + o->box.ul.x;
- o->boxT.ul.x = MU2TILE(o->box.ul.x);
- o->boxT.lr.x = MU2TILE(o->box.lr.x);
- o->boxT.ul.y = MU2TILE(o->box.ul.y);
- o->boxT.lr.y = MU2TILE(o->box.lr.y);
- o->boxTXmid = MU2TILE(o->boxXmid);
- }
- // update offset
- o->offs.x += o->pos.x - xpos_0;
- o->offs.y += o->pos.y - ypos_0;
- }
- }
- // special clipping for sprite types 0xB and 0x16 (slicestar and sphereful)
- // TODO: recheck
- void FullClipToWalls(objtype *o)
- {
- unsigned xpos_0, ypos_0;
- int del_x, del_y;
- spritetabletype far *sprhead_p;
- /* limit and apply vel */
- xpos_0 = o->pos.x;
- ypos_0 = o->pos.y;
- if (KeenVel.x > 239)
- KeenVel.x = 239;
- else if (KeenVel.x < -239)
- KeenVel.y = -239;
- if (KeenVel.y > 255)
- KeenVel.y = 255;
- else if (KeenVel.y < -239)
- KeenVel.y = -239;
- o->pos.x += KeenVel.x;
- o->pos.y += KeenVel.y;
- o->draw = true;
- sprhead_p = spritetable + (o->chunk - STARTSPRITES);
- if (o->type != 0xB && o->type != 0x16) {
- Quit("FullClipToWalls: Bad obclass");
- }
- /* Make Artificial Hitbox */
- del_x = del_y = 0x200;
- o->box.lr.x = o->pos.x + del_x;
- o->box.ul.x = o->pos.x;
- o->box.ul.y = o->pos.y;
- o->box.lr.y = o->pos.y + del_y;
- o->boxT.ul.x = MU2TILE(o->box.ul.x);
- o->boxT.lr.x = MU2TILE(o->box.lr.x);
- o->boxT.ul.y = MU2TILE(o->box.ul.y);
- o->boxT.lr.y = MU2TILE(o->box.lr.y);
- /* Do Tile Checking */
- o->leftflags = o->botflags = o->topflags = o->rightflags = 0;
- if (!CheckIfStuck(o))
- {
- UpdateXPos(o, -KeenVel.x);
- if (!CheckIfStuck(o))
- {
- if (KeenVel.y > 0)
- o->topflags = 1;
- else
- o->botflags = 1;
- UpdateXPos(o, KeenVel.x);
- UpdateYPos(o, KeenVel.y);
- if (!CheckIfStuck(o))
- {
- UpdateXPos(o, -KeenVel.x);
- if (KeenVel.x > 0)
- o->leftflags = 1;
- else
- o->rightflags = 1;
- }
- }
- else
- {
- if (KeenVel.x > 0)
- o->leftflags = 1;
- else
- o->rightflags = 1;
- }
- }
- /* Set box using spriteahd */
- o->offs.x += (o->pos.x - xpos_0);
- o->offs.y += (o->pos.y - ypos_0);
- o->box.ul.x = o->pos.x + sprhead_p->xl;
- o->box.lr.x = o->pos.x + sprhead_p->xh;
- o->box.ul.y = o->pos.y + sprhead_p->yl;
- o->box.lr.y = o->pos.y + sprhead_p->yh;
- o->boxXmid = (o->box.lr.x-o->box.ul.x)/2 + o->box.ul.x;
- }
- // rehcek
- void SimpleClip(objtype *o)
- {
- unsigned xpos_0, ypos_0;
- spritetabletype far *sprhead_p;
- /* update object position */
- xpos_0 = o->pos.x;
- ypos_0 = o->pos.y;
- o->pos.x += KeenVel.x;
- o->pos.y += KeenVel.y;
- o->draw = true;
- if (o->chunk)
- {
- /* Set Temp Dimensions */
- sprhead_p = spritetable + (o->chunk - STARTSPRITES);
- KeenBoxT.ul.x = o->boxT.ul.x;
- KeenBoxT.lr.x = o->boxT.lr.x;
- KeenBoxT.ul.y = o->boxT.ul.y;
- KeenBoxT.lr.y = o->boxT.lr.y;
- KeenBoxTXMid = o->boxTXmid;
- KeenBox.ul.x = o->box.ul.x;
- KeenBox.lr.x = o->box.lr.x;
- KeenBox.ul.y = o->box.ul.y;
- KeenBox.lr.y = o->box.lr.y;
- KeenBoxXMid = o->boxXmid;
- /* Set new box according to sprhead + vel */
- o->box.ul.x = o->pos.x + sprhead_p->xl;
- o->box.lr.x = o->pos.x + sprhead_p->xh;
- o->box.ul.y = o->pos.y + sprhead_p->yl;
- o->box.lr.y = o->pos.y + sprhead_p->yh;
- o->boxXmid = (o->box.lr.x-o->box.ul.x)/2 + o->box.ul.x;
- o->boxT.ul.x = MU2TILE(o->box.ul.x);
- o->boxT.lr.x = MU2TILE(o->box.lr.x);
- o->boxT.ul.y = MU2TILE(o->box.ul.y);
- o->boxT.lr.y = MU2TILE(o->box.lr.y);
- o->boxTXmid = MU2TILE(o->boxXmid);
- /* Do Tile Checking */
- o->leftflags = o->botflags = o->rightflags = o->leftflags = 0;
- if (o->clipping)
- {
- KeenClip.ul.x = o->box.ul.x - KeenBox.ul.x;
- KeenClip.lr.x = o->box.lr.x - KeenBox.lr.x;
- KeenClip.ul.y = o->box.ul.y - KeenBox.ul.y;
- KeenClip.lr.y = o->box.lr.y - KeenBox.lr.y;
- KeenClipXMid = o->boxXmid - KeenBoxXMid;
- SetOnSlope(o);
- MoveOutOfTileHorz(o);
- }
- /* calc offset */
- o->offs.x += o->pos.x - xpos_0;
- o->offs.y += o->pos.y - ypos_0;
- }
- }
- // recheck
- /*
- ============================
- =
- = PushHorz
- =
- = o2 pushes o1 in x
- =
- ============================
- */
- void PushHorz(objtype *o1, objtype *o2)
- {
- int del_offsX, del_boxXA, del_boxXB;
- del_offsX = o2->offs.x - o1->offs.x;
- del_boxXA = o2->box.lr.x - o1->box.ul.x;
- del_boxXB = o1->box.lr.x - o2->box.ul.x;
- if (del_boxXA > 0 && del_boxXA <= del_offsX)
- {
- KeenVel.x = del_boxXA;
- if (o1->action->change_v)
- KeenVel.y = -del_boxXA + 16;
- NormalClip(o1);
- o1->rightflags = 1;
- return;
- }
- if (del_boxXB > 0 && del_boxXB >= -del_offsX)
- {
- KeenVel.x = -del_boxXB;
- if (o1->action->change_v)
- KeenVel.y = del_boxXB + 16;
- NormalClip(o1);
- o1->leftflags = 1;
- return;
- }
- }
- /*
- ============================
- =
- = PushVert
- =
- = o2 carries o1
- =
- ============================
- */
- void PushVert(objtype *o1, objtype *o2)
- {
- int del_boxY, del_offsY, action_change_v;
- del_offsY = o1->offs.y - o2->offs.y;
- del_boxY = o1->box.lr.y - o2->box.ul.y;
- if (del_boxY >= 0 && del_boxY <= del_offsY)
- {
- if (o1->type == obj_keen)
- PDat->Platform = o2;
- /* Move carried sprite around */
- KeenVel.y = -del_boxY;
- action_change_v = o1->action->change_v;
- o1->action->change_v = 0;
- NormalClip(o1);
- o1->action->change_v = action_change_v;
- if (o1->botflags == BF_NOT)
- o1->topflags = TF_PLATFORM;
- }
- }
- void sub_19E88(arg0,arg2,arg4) {
- // no xrefs, skipping for now
- }
- // Function that runs the actions
- // Rechecked
- // MoveParms
- // 0
- // 1
- // 2: Do action once per loop, don't add action delta/v or h, use actiontimer as countdown
- // 3
- // 4
- // o->int13 is some time scaling factor, reset at middle
- int TimeAction(objtype *o, int time)
- {
- actiontype *a;
- int newtime, timeleft, newtimeleft;
- a = o->action;
- // Move Parm 2 == Use actiontimer as loopcounter
- // Only think() once per DoAction call (returns 0)
- if (a->moveparm == 2)
- {
- if (a->think)
- {
- if (o->actiontimer)
- o->actiontimer--;
- else
- a->think(o);
- }
- return 0;
- }
- // Increase tics;
- newtime = time + o->int13;
- if (a->delay > newtime || a->delay == 0)
- {
- // Haven't yet reached action time limit
- o->int13 = newtime;
- // 1, 4: Use action delta scaled by time for motion
- if (a->moveparm == 1 || a->moveparm == 4)
- {
- if (o->xmotion)
- KeenVel.x += a->delta_h * (o->xmotion==motion_Right?time:-time);
- if (o->ymotion)
- KeenVel.y += a->delta_v * (o->ymotion==motion_Down?time:-time);
- }
- //1a078
- // 3, 4 Burn fuse and do think
- if (a->moveparm == 4 || a->moveparm == 3)
- {
- if (a->think)
- {
- if (o->actiontimer)
- o->actiontimer--;
- else
- a->think(o);
- }
- }
- // No leftover tics to do for NEXT action
- return 0;
- }
- //1A0A6
- // Action time delay reached
- // timeleft = the final number of tics to perform for this action
- // newtimeleft = the overflow to apply to the next action
- timeleft = a->delay - o->int13;
- newtimeleft = newtime - a->delay;
- o->int13 = 0; // reset tics
- // 1, 4: Use action delta scaled by remainder of tics for current action
- if (a->moveparm == 1 || a->moveparm == 4)
- {
- //1ac09
- if (o->xmotion)
- KeenVel.x += a->delta_h * (o->xmotion==motion_Right?timeleft:-timeleft);
- if (o->ymotion)
- KeenVel.y += a->delta_v * (o->ymotion==motion_Down?timeleft:-timeleft);
- }
- else // moveparm == 3, 0, Move by unscaled amount at action start
- {
- if (o->xmotion)
- KeenVel.x += (o->xmotion==motion_Right?a->delta_h:-a->delta_h);
- if (o->ymotion)
- KeenVel.y += (o->ymotion==motion_Down?a->delta_v:-a->delta_v);
- }
- //1a141
- // Burn fuse and think()
- if (a->think)
- {
- if (o->actiontimer)
- o->actiontimer--;
- else
- a->think(o);
- }
- // Advance action if haven't done so
- if (o->action == a)
- o->action = a->next;
- else if (!o->action) // if NULL action, then sprite is dead
- return 0;
- // If action advanced, want to process remaining tics on the next action
- return newtimeleft;
- }
- // Rechecked
- void DoAction(objtype *o)
- {
- int frame_0, time;
- actiontype *a;
- // Set the offset and clipping offset to this frame to zero
- o->offs.x = o->offs.y = KeenVel.x = KeenVel.y = 0;
- frame_0 = o->chunk;
- a = o->action;
- // Process action once
- time = TimeAction(o,SpriteSync);
- // reset counter if new action
- if (o->action != a)
- {
- o->int13 = 0;
- a = o->action;
- }
- // If moved into a new action while performing old action
- // then do action(s) for remainder of tics
- while (time)
- {
- if (a->change_h || a->delay > time)
- time = TimeAction(o, time);
- else
- time = TimeAction(o, a->delay - 1);
- // reset counter if new action
- if (o->action != a)
- {
- o->int13 = 0;
- a = o->action;
- }
- }
- // NULL action == remove object
- if (a == NULL)
- {
- RemoveObj(o);
- return;
- }
- // Set Sprite chunk
- if (a->right_chunk)
- o->chunk=(o->xmotion>motion_None)? a->right_chunk : a->left_chunk;
- if (o->chunk == -1)
- o->chunk = 0;
- // If we have moved, frame has changed, or on platform, then do clipping
- if (KeenVel.x != 0 || KeenVel.y != 0 ||
- o->chunk != frame_0 || o->topflags == TF_PLATFORM)
- {
- if (o->clipping == 2)
- FullClipToWalls(o);
- else
- NormalClip(o);
- }
- }
- //The "check ground" funcs look to be setting an action to a sprite
- // rechecked -- perfect
- void CheckGround(objtype *o, actiontype *a)
- {
- int clip_0;
- o->action = a;
- if (a->right_chunk)
- o->chunk = (o->xmotion > motion_None)? a->right_chunk : a->left_chunk;
- if (o->chunk == -1)
- o->chunk = 0;
- clip_0 = o->clipping;
- o->clipping = 0;
- KeenVel.x = KeenVel.y = 0;
- NormalClip(o);
- o->clipping = clip_0;
- // Special clipping
- if (o->clipping == 2)
- {
- FullClipToWalls(o);
- return;
- }
- if (o->clipping == 1)
- NormalClip(o);
- }
- // rechecked -- perfect
- void CheckGround2(objtype *o, ACTION *a)
- {
- o->action = a;
- o->int13 = 0;
- if (a->right_chunk)
- o->chunk = (o->xmotion > motion_None)? a->right_chunk : a->left_chunk;
- if (o->chunk == -1)
- o->chunk = 0;
- o->draw = true;
- KeenVel.x = KeenVel.y = 0;
- if (o->topflags != TF_PLATFORM)
- NormalClip(o);
- }
- /*
- ============================
- =
- = ObjectVisible
- =
- = Returns true if object on screen
- =
- ============================
- */
- boolean ObjectVisible(objtype *o)
- {
- if (o->boxT.lr.x >= ScrollX0_T && o->boxT.lr.x >= ScrollY0_T &&
- o->boxT.ul.x <= ScrollX1_T && o->boxT.ul.y <= ScrollY1_T)
- return true;
- return false;
- }
- // ===========================================================================
- //
- // Generic Object Functions
- //
- // ===========================================================================
- /*
- ============================
- =
- = AddGravity / AddGravity2 / AddGravity3
- =
- = Make objects fall (at various accelerations)
- =
- ============================
- */
- // rechecked -- perfect
- void AddGravity(objtype *o)
- {
- unsigned long tc;
- for (tc = gameticks_2 - SpriteSync; tc < gameticks_2; tc++)
- {
- if (tc & 1)
- {
- if (o->vel.y < 0 && o->vel.y >= -4)
- {
- KeenVel.y += o->vel.y;
- o->vel.y = 0;
- return;
- }
- o->vel.y += 4; //4 appears to be gravity
- if (o->vel.y > 70)
- o->vel.y = 70; // 70 is max gravity
- }
- KeenVel.y += o->vel.y;
- }
- }
- // rechecked -- perfect
- void AddGravity2(objtype *o)
- {
- unsigned long tc;
- for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++)
- {
- if (tc & 1)
- {
- if (o->vel.y < 0 && o->vel.y >= -3)
- {
- KeenVel.y += o->vel.y;
- o->vel.y = 0;
- return;
- }
- o->vel.y += 3; // 3 is gravity
- if (o->vel.y > 70)
- o->vel.y = 70; // 70 is max gravity
- }
- KeenVel.y += o->vel.y;
- }
- }
- // rechecked -- good
- void AddGravity3(objtype *o)
- {
- unsigned long tc;
- for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++)
- {
- if ((tc?0:1) & 3)
- {
- if (++o->vel.y > 70)
- o->vel.y = 70;
- }
- KeenVel.y += o->vel.y;
- }
- }
- // rechecked -- perfect
- void MoveHorz0(objtype *o, int delX, int xlimit)
- {
- unsigned long tc;
- unsigned d;
- // sign byte
- d = (unsigned)o->vel.x & 0x8000;
- for (tc = gameticks_2 - SpriteSync; tc < gameticks_2; tc++)
- {
- if (tc & 1)
- {
- o->vel.x += delX;
- if (((unsigned)o->vel.x & 0x8000) != d)
- {
- d = (unsigned)o->vel.x & 0x8000;
- o->xmotion = d? motion_Left : motion_Right;
- }
- if (o->vel.x > xlimit)
- o->vel.x = xlimit;
- else if (o->vel.x < -xlimit)
- o->vel.x = -xlimit;
- }
- KeenVel.x += o->vel.x;
- }
- }
- // no xrefs in keen5
- void MoveHorz1(objtype *o, Motion xmotion, int xlimit)
- {
- unsigned long tc;
- for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++)
- {
- if (tc &1)
- {
- o->vel.x += xmotion;
- if (o->vel.x > xlimit)
- o->vel.x = xlimit;
- else if (o->vel.x < -xlimit)
- o->vel.x = -xlimit;
- }
- KeenVel.x += o->vel.x;
- }
- }
- // no xrefs in keen5
- void MoveVert1(objtype *o, Motion ymotion, int ylimit)
- {
- unsigned long tc;
- for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++) {
- if (tc &1)
- {
- o->vel.y += ymotion;
- if (o->vel.y > ylimit)
- o->vel.y = ylimit;
- else if (o->vel.y < -ylimit)
- o->vel.y = -ylimit;
- }
- KeenVel.y += o->vel.y;
- }
- return;
- }
- /*
- ============================
- =
- = MoveHorz2 / MoveVert2
- =
- = Gently slow down in x/y
- =
- ============================
- */
- // rechecked -- perfect
- void MoveHorz2(objtype *o)
- {
- unsigned long tc;
- int d, xadj;
- d = o->vel.x & 0x8000;
- if (o->vel.x > 0)
- xadj = -1;
- else if (o->vel.x < 0)
- xadj = 1;
- else
- xadj = 0;
- for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++)
- {
- if (tc & 1)
- {
- o->vel.x += xadj;
- if ((o->vel.x & 0x8000) != d)
- o->vel.x = 0;
- }
- KeenVel.x += o->vel.x;
- }
- }
- // no xrefs
- // note d is used before initialized
- void MoveVert2(objtype *o)
- {
- unsigned long tc;
- int d, yadj;
- d = o->vel.x & 0x8000; // this line not in source, but probably should be?
- if (o->vel.y > 0)
- yadj = -1;
- else if (o->vel.y < 0)
- yadj = 1;
- else
- yadj = 0;
- for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++)
- {
- if (tc & 1)
- {
- o->vel.y += yadj;
- if ((o->vel.y & 0x8000) == d)
- o->vel.y = 0;
- }
- KeenVel.y += o->vel.y;
- }
- }
- //something to do with getting shot by keen?
- #if 0
- StunCreature(objtype *o, objtype *stunner, ACTION *a)
- {
- StunnerHits(stunner);
- o->int33 = o->state = o->time = 0;
- o->int34 = o->type;
- CheckGround2(o, a);
- o->type = 7;
- o->vel.y -= 24;
- if (o->vel.y < -48) o->vel.y = -48;
- return;
- }
- #endif
- /*Sprite Bheaviours*/
- //default falling
- // rechecked -- perfect
- void Fall(objtype *o)
- {
- AddGravity(o);
- KeenVel.x = o->vel.x * SpriteSync;
- }
- //used by Master Shot
- // rechecked -- perfect
- void Fall2(objtype *o)
- {
- AddGravity2(o);
- KeenVel.x = o->vel.x * SpriteSync;
- }
- //move without gravity, used by GunShots
- // rechecked -- perfect
- void Glide(objtype *o)
- {
- KeenVel.x = o->vel.x * SpriteSync;
- KeenVel.y = o->vel.y * SpriteSync;
- }
- //no xrefs
- //just draw the sprite
- // rechecked -- perfect
- void Think0(objtype *o)
- {
- o->draw = true;
- }
- // no xrefs
- // cycle through states
- // rechecked -- perfect
- void Think1(objtype *o)
- {
- o->time = 0;
- o->draw = 1;
- if (++(o->state) == 3)
- o->state = 0;
- }
- /*Sprite Collision Functions */
- //usedby ShelleyBits, Polezaps, for killling keen
- void SprCol1(objtype *o1, objtype *o2)
- {
- o1++;
- if (o2->type == obj_keen)
- KeenDie(o2);
- }
- /*Draw Funcs*/
- // note: in keen, there is no active checking
- void DrawFunc1(objtype *o)
- {
- RF_PlaceSprite(&o->spritedraw, o->pos.x, o->pos.y, o->chunk, 0, o->int16);
- }
- //used by scotty
- void DrawFunc2(objtype *o)
- {
- if (o->xmotion == motion_Right && o->leftflags)
- {
- o->pos.x -= o->offs.x;
- o->xmotion = motion_Left;
- o->actiontimer = US_RndT() / 32;
- CheckGround2(o, o->action);
- }
- else if (o->xmotion == motion_Left && o->rightflags)
- {
- o->pos.x -= o->offs.x;
- o->xmotion = motion_Right;
- o->actiontimer = US_RndT()/32;
- CheckGround2(o,o->action);
- }
- else if (!o->topflags)
- {
- o->pos.x -= o->offs.x;
- o->xmotion = -o->xmotion;
- o->actiontimer = US_RndT()/32;
- CheckGround2(o,o->action);
- }
- RF_PlaceSprite(&o->spritedraw, o->pos.x, o->pos.y, o->chunk, 0, o->int16);
- }
- //no xrefs in Keen5, skipping for now
- void DrawFunc3(objtype *o) {
- }
- void ObjBadState(void) {
- Quit("Object with a bad state!");
- return;
- }
- /* Looks like stunner stars */
- #if 0
- void DrawFunc4(objtype *o) {
- int delx, dely;
- if (o->leftflags || o->rightflags)
- o->vel.x = 0;
- if (o->botflags)
- o->vel.y = 0;
- if (o->topflags)
- {
- o->vel.x = o->vel.y = 0;
- if (o->action->next)
- CheckGround2(o, o->action->next);
- }
- RF_PlaceSprite(&o->spritedraw, o->pos.x, o->pos.y, o->chunk, 0, o->int16);
- /* Place The Stunner Stars
- Remember To RF_RemoveSprite in PlayLoop!
- */
- dely = delx = 0;
- if (o->int34 == 9) {
- delx += 64;
- } else if (o->int34 == 15) {
- dely -= 128;
- } else if (o->int34 == 0x17) {
- dely -= 128;
- }
- o->time += SpriteSync;
- if (o->time > 10) {
- o->time -= 10;
- if (++(o->state) == 3)
- o->state = 0;
- }
- RF_PlaceSprite(&(SpriteDraw*)o->int33, o->pos.x+delx, o->pos.y+dely, o->state+143, 0, 3);
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement