⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p_map.c

📁 The source code of Doom legacy for windows
💻 C
📖 第 1 页 / 共 5 页
字号:
        // damage / explode        damage = ((P_Random()%8)+1)*tmthing->info->damage;        if( P_DamageMobj (thing, tmthing, tmthing->target, damage) && (thing->flags & MF_NOBLOOD)==0 && demoversion>=129 )            P_SpawnBloodSplats (tmthing->x,tmthing->y,tmthing->z, damage, thing->momx, thing->momy);        // don't traverse any more        return false;    }    if (thing->flags2 & MF2_PUSHABLE && !(tmthing->flags2 & MF2_CANNOTPUSH))    {                         // Push thing        thing->momx += tmthing->momx >> 2;        thing->momy += tmthing->momy >> 2;    }    // check for special pickup    if (thing->flags & MF_SPECIAL)    {        solid = thing->flags&MF_SOLID;        if (tmflags&MF_PICKUP)        {            // can remove thing            P_TouchSpecialThing (thing, tmthing);        }        return !solid;    }    // check again for special pickup    if(demoversion>=132 && tmthing->flags & MF_SPECIAL)    {        solid = tmthing->flags&MF_SOLID;        if (thing->flags&MF_PICKUP)        {            // can remove thing            P_TouchSpecialThing (tmthing, thing);        }        return !solid;    }    //added:24-02-98:compatibility with old demos, it used to return with...    //added:27-02-98:for version 112+, nonsolid things pass through other things    if (demoversion<112 || demoversion>=132 || !(tmthing->flags & MF_SOLID))        return !(thing->flags & MF_SOLID);    //added:22-02-98: added z checking at last    //SoM: 3/10/2000: Treat noclip things as non-solid!    if ((thing->flags & MF_SOLID) && (tmthing->flags & MF_SOLID) &&        !(thing->flags & MF_NOCLIP) && !(tmthing->flags & MF_NOCLIP))    {        // pass under        tmtopz = tmthing->z + tmthing->height;        if ( tmtopz < thing->z)        {            if (thing->z < tmceilingz)                tmceilingz = thing->z;            return true;        }        topz = thing->z + thing->height + FRACUNIT;        // block only when jumping not high enough,        // (dont climb max. 24units while already in air)        // if not in air, let P_TryMove() decide if its not too high        if (tmthing->player &&            tmthing->z < topz &&            tmthing->z > tmthing->floorz)  // block while in air            return false;        if (topz > tmfloorz)        {            tmfloorz = topz;            tmfloorthing = thing;       //thing we may stand on        }    }    // not solid not blocked    return true;}// SoM: 3/15/2000// PIT_CrossLine// Checks to see if a PE->LS trajectory line crosses a blocking// line. Returns false if it does.//// tmbbox holds the bounding box of the trajectory. If that box// does not touch the bounding box of the line in question,// then the trajectory is not blocked. If the PE is on one side// of the line and the LS is on the other side, then the// trajectory is blocked.//// Currently this assumes an infinite line, which is not quite// correct. A more correct solution would be to check for an// intersection of the trajectory and the line, but that takes// longer and probably really isn't worth the effort.//static boolean PIT_CrossLine (line_t* ld)  {  if (!(ld->flags & ML_TWOSIDED) ||      (ld->flags & (ML_BLOCKING|ML_BLOCKMONSTERS)))    if (!(tmbbox[BOXLEFT]   > ld->bbox[BOXRIGHT]  ||          tmbbox[BOXRIGHT]  < ld->bbox[BOXLEFT]   ||          tmbbox[BOXTOP]    < ld->bbox[BOXBOTTOM] ||          tmbbox[BOXBOTTOM] > ld->bbox[BOXTOP]))      if (P_PointOnLineSide(pe_x,pe_y,ld) != P_PointOnLineSide(ls_x,ls_y,ld))        return(false);  // line blocks trajectory  return(true); // line doesn't block trajectory  }//// P_CheckWallPortals// Checks a lines wallportal list to see if a mobj can pass through one of// them... returns NULL if a mobj can't pass through, otherwise, returns a// pointer to the portal the thing is passing through.wallportal_t*  P_CheckWallPortals(mobj_t* thing, line_t* line){  wallportal_t*  wpr;  fixed_t        thingtop, thingbot;  if(!line->wallportals)    return NULL;  thingbot = thing->z;  thingtop = thingbot + thing->height;  for(wpr = line->wallportals; wpr; wpr = wpr->next)    if(thingtop > *wpr->bottomheight && thingbot < *wpr->topheight)      return wpr;  return NULL;}//// PIT_CheckLine// Adjusts tmfloorz and tmceilingz as lines are contacted//boolean PIT_CheckLine (line_t* ld){    wallportal_t*    wpr = NULL;    if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]        || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]        || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]        || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )        return true;    if (P_BoxOnLineSide (tmbbox, ld) != -1)        return true;    // A line has been hit    // The moving thing's destination position will cross    // the given line.    // If this should not be allowed, return false.    // If the line is special, keep track of it    // to process later if the move is proven ok.    // NOTE: specials are NOT sorted by order,    // so two special lines that are only 8 pixels apart    // could be crossed in either order.    // 10-12-99 BP: moved this line to out of the if so upper and     //              lower texture can be hit by a splat    blockingline = ld;    if (!ld->backsector)    {      if(ld->wallportals && (wpr = P_CheckWallPortals(tmthing, ld)))        goto ldspecial;      if(demoversion>=132 && tmthing->flags & MF_MISSILE && ld->special)        add_spechit(ld);      return false;           // one sided line    }    // missil and Camera can cross uncrossable line    if (!(tmthing->flags & MF_MISSILE) &&        !(tmthing->type == MT_CHASECAM) )    {        if (ld->flags & ML_BLOCKING)            return false;       // explicitly blocking everything        if ( !(tmthing->player) &&             ld->flags & ML_BLOCKMONSTERS )            return false;       // block monsters only    }    // set openrange, opentop, openbottom    P_LineOpening (ld);    // adjust floor / ceiling heights    if (opentop < tmceilingz)    {        tmsectorceilingz = tmceilingz = opentop;        ceilingline = ld;    }    if (openbottom > tmfloorz)        tmsectorfloorz = tmfloorz = openbottom;    if (lowfloor < tmdropoffz)        tmdropoffz = lowfloor;    if((wpr = P_CheckWallPortals(tmthing, ld)))    {      tmfloorz = tmsectorfloorz = openbottom;      tmceilingz = tmsectorceilingz = opentop;    }    ldspecial:    if(ld->wallportals && wpr)    {      fixed_t         bx, by, xl, xh, yl, yh;      fixed_t         xoff, yoff;      fixed_t         oldbox[4];      wpr->portal->mline->validcount = validcount;      // Store the old bounding box (for recursive purposes)      for(bx = 0; bx < 4; bx++)        oldbox[bx] = tmbbox[bx];      xoff = (wpr->portal->mline->v2->x - ld->v1->x);      yoff = (wpr->portal->mline->v2->y - ld->v1->y);      tmbbox[BOXTOP] += yoff;      tmbbox[BOXBOTTOM] += yoff;      tmbbox[BOXLEFT] += xoff;      tmbbox[BOXRIGHT] += xoff;      // SoM: Check lines on the "other side" of the portal...      if(!(tmthing->flags & MF_NOCLIPTHING))      {        xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;        xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;        yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;        yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;                for (bx=xl ; bx<=xh ; bx++)          for (by=yl ; by<=yh ; by++)            if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))              return false;      }      // check lines      xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;      xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;      yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;      yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;      for (bx=xl ; bx<=xh ; bx++)        for (by=yl ; by<=yh ; by++)          if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))            return false;      for(bx = 0; bx < 4; bx++)        tmbbox[bx] = oldbox[bx];    }    // if contacted a special line, add it to the list    if (ld->special)      add_spechit(ld);    return true;}// =========================================================================//                         MOVEMENT CLIPPING// =========================================================================//// P_CheckPosition// This is purely informative, nothing is modified// (except things picked up).//// in://  a mobj_t (can be valid or invalid)//  a position to be checked//   (doesn't need to be related to the mobj_t->x,y)//// during://  special things are touched if MF_PICKUP//  early out on solid lines?//// out://  newsubsec//  tmfloorz//  tmceilingz//  tmdropoffz//   the lowest point contacted//   (monsters won't move to a dropoff)//  speciallines[]//  numspeciallines////added:27-02-98://// tmfloorz//     the nearest floor or thing's top under tmthing// tmceilingz//     the nearest ceiling or thing's bottom over tmthing//boolean P_CheckPosition ( mobj_t*       thing,                          fixed_t       x,                          fixed_t       y ){    int                 xl;    int                 xh;    int                 yl;    int                 yh;    int                 bx;    int                 by;    subsector_t*        newsubsec;    tmthing = thing;    tmflags = thing->flags;    tmx = x;    tmy = y;    tmbbox[BOXTOP] = y + tmthing->radius;    tmbbox[BOXBOTTOM] = y - tmthing->radius;    tmbbox[BOXRIGHT] = x + tmthing->radius;    tmbbox[BOXLEFT] = x - tmthing->radius;    newsubsec = R_PointInSubsector (x,y);    ceilingline = blockingline = NULL;    // The base floor / ceiling is from the subsector    // that contains the point.    // Any contacted lines the step closer together    // will adjust them.    tmfloorz = tmsectorfloorz = tmdropoffz = newsubsec->sector->floorheight;    tmceilingz = tmsectorceilingz = newsubsec->sector->ceilingheight;    //SoM: 3/23/2000: Check list of fake floors and see if    //tmfloorz/tmceilingz need to be altered.    if(newsubsec->sector->ffloors)    {      ffloor_t*  rover;      fixed_t    delta1;      fixed_t    delta2;      int        thingtop = thing->z + thing->height;      for(rover = newsubsec->sector->ffloors; rover; rover = rover->next)      {        if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;        delta1 = thing->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));        delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));        if(*rover->topheight > tmfloorz && abs(delta1) < abs(delta2))          tmfloorz = tmdropoffz = *rover->topheight;        if(*rover->bottomheight < tmceilingz && abs(delta1) >= abs(delta2))          tmceilingz = *rover->bottomheight;      }    }    // tmfloorthing is set when tmfloorz comes from a thing's top    tmfloorthing = NULL;    validcount++;    numspechit = 0;    if ( tmflags & MF_NOCLIP )        return true;    // Check things first, possibly picking things up.    // The bounding box is extended by MAXRADIUS    // because mobj_ts are grouped into mapblocks    // based on their origin point, and can overlap    // into adjacent blocks by up to MAXRADIUS units.    // BP: added MF_NOCLIPTHING :used by camera to don't be blocked by things    if(!(thing->flags & MF_NOCLIPTHING))    {        xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;        xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;        yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;        yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;                for (bx=xl ; bx<=xh ; bx++)            for (by=yl ; by<=yh ; by++)                if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))                    return false;    }    // check lines    xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;    xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;    yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;    yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;    for (bx=xl ; bx<=xh ; bx++)        for (by=yl ; by<=yh ; by++)            if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))                return false;    return true;}//==========================================================================//// CheckMissileImpact////==========================================================================static void CheckMissileImpact(mobj_t *mobj){    int i;        if( demoversion<132 || !numspechit || !(mobj->flags&MF_MISSILE) || !mobj->target)        return;    if(!mobj->target->player)        return;    for(i = numspechit-1; i >= 0; i--)        P_ShootSpecialLine(mobj->target, lines + spechit[i]);}//// P_TryMove// Attempt to move to a new position,// crossing special lines unless MF_TELEPORT is set.//boolean P_TryMove ( mobj_t*       thing,                    fixed_t       x,                    fixed_t       y,                    boolean       allowdropoff){    fixed_t     oldx;    fixed_t     oldy;    int         side;    int         oldside;    line_t*     ld;    floatok = false;    if (!P_CheckPosition (thing, x, y))    {        CheckMissileImpact(thing);        return false;           // solid wall or thing    }#ifdef CLIENTPREDICTION2    if ( !(thing->flags & MF_NOCLIP) && !(thing->eflags & MF_NOZCHECKING))#else    if ( !(thing->flags & MF_NOCLIP) )#endif    {        fixed_t maxstep = MAXSTEPMOVE;        if (tmceilingz - tmfloorz < thing->height)        {            CheckMissileImpact(thing);            return false;       // doesn't fit        }        floatok = true;        if ( !(thing->flags & MF_TELEPORT)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -