예제 #1
0
//
// Reads the raw vertices and obtains final ones
//
void UDMFParser::loadVertices() const
{
   numvertexes = (int)mVertices.getLength();
   vertexes = estructalloctag(vertex_t, numvertexes, PU_LEVEL);
   for(int i = 0; i < numvertexes; i++)
   {
      vertexes[i].x = mVertices[i].x;
      vertexes[i].y = mVertices[i].y;
      // SoM: Cardboard stores float versions of vertices.
      vertexes[i].fx = M_FixedToFloat(vertexes[i].x);
      vertexes[i].fy = M_FixedToFloat(vertexes[i].y);
   }
}
예제 #2
0
//
// R_BuildDynaBSP
//
// Call to build a dynamic BSP sub-tree for sorting of dynasegs.
//
rpolybsp_t *R_BuildDynaBSP(subsector_t *subsec)
{
   rpolybsp_t *bsp = NULL;
   dseglist_t segs = NULL;

   if(R_collapseFragmentsToDSList(subsec, &segs))
   {
      bsp = estructalloctag(rpolybsp_t, 1, PU_LEVEL);
      bsp->dirty = false;
      bsp->root = R_createNode(&segs);
   }

   return bsp;
}
예제 #3
0
//
// R_CreatePortal
//
// Function to internally create a new portal.
//
static portal_t *R_CreatePortal()
{
   portal_t *ret = estructalloctag(portal_t, 1, PU_LEVEL);

   if(!portals)
      portals = last = ret;
   else
   {
      last->next = ret;
      last = ret;
   }
   
   ret->poverlay  = R_NewPlaneHash(32);
   ret->globaltex = 1;

   return ret;
}
예제 #4
0
static pwindow_t *newPortalWindow()
{
   pwindow_t *ret;

   if(unusedhead)
   {
      ret = unusedhead;
      unusedhead = unusedhead->next;
   }
   else
   {
      ret = estructalloctag(pwindow_t, 1, PU_LEVEL);
      
      float *buf  = emalloctag(float *, 2*video.width*sizeof(float), PU_LEVEL, NULL);
      ret->top    = buf;
      ret->bottom = buf + video.width;
   }

   R_ClearPortalWindow(ret);
   
   return ret;
}
예제 #5
0
//
// ACS_LoadScriptACS0
//
void ACS_LoadScriptACS0(ACSVM *vm, WadDirectory *dir, int lump, byte *data)
{
   uint32_t lumpAvail; // Used in bounds checking.
   uint32_t lumpLength = dir->lumpLength(lump);
   int32_t *rover;
   uint32_t tableIndex;

   // Header + table index + script count + string count = 16 bytes.
   if (lumpLength < 16) return;
   lumpAvail = lumpLength - 16;

   rover = (int32_t *)data + 1;

   // Find script table.
   tableIndex = SwapLong(*rover);

   // Aha, but there might really be an ACSE header here!
   if(tableIndex >= 8 && tableIndex <= lumpLength)
   {
      uint32_t fakeHeader = SwapULong(*(uint32_t *)(data + tableIndex - 4));

      if(fakeHeader == ACS_CHUNKID('A', 'C', 'S', 'E'))
      {
         ACS_LoadScriptACSE(vm, dir, lump, data, tableIndex - 8);
         return;
      }
      else if(fakeHeader == ACS_CHUNKID('A', 'C', 'S', 'e'))
      {
         ACS_LoadScriptACSe(vm, dir, lump, data, tableIndex - 8);
         return;
      }
   }

   // At the index there must be at least the script count and string count.
   // Subtracting from lumpLength instead of adding to tableIndex in case the
   // latter would cause an overflow.
   if (tableIndex > lumpLength - 8) return;

   rover = (int32_t *)(data + tableIndex);

   // Read script count.
   vm->numScripts = SwapLong(*rover++);

   // Verify that there is enough space for the given number of scripts.
   if (vm->numScripts * 12 > lumpAvail) return;
   lumpAvail -= vm->numScripts * 12;

   // Also verify that the string count will be inside the lump.
   if (tableIndex + 8 > lumpLength - (vm->numScripts * 12)) return;
   tableIndex += 8 + (vm->numScripts * 12);

   // Read scripts.
   vm->scripts = estructalloctag(ACSScript, vm->numScripts, PU_LEVEL);

   for(ACSScript *itr = vm->scripts, *end = itr + vm->numScripts; itr != end; ++itr)
   {
      itr->number    = SwapLong(*rover++);
      itr->codeIndex = SwapLong(*rover++);
      itr->numArgs   = SwapLong(*rover++);

      itr->numVars   = ACS_NUM_LOCALVARS;
      itr->vm        = vm;

      if(itr->number >= 1000)
      {
         itr->type = ACS_STYPE_OPEN;
         itr->number -= 1000;
      }
      else
         itr->type = ACS_STYPE_CLOSED;
   }

   // Read string count.
   vm->numStrings = SwapLong(*rover++);

   // Again, verify that there is enough space for the table first.
   if (vm->numStrings * 4 > lumpAvail) return;
   lumpAvail -= vm->numStrings * 4;

   // This time, just verify the end of the table is in bounds.
   if (tableIndex > lumpLength - (vm->numStrings * 4)) return;

   // Read strings.
   vm->strings = (uint32_t *)Z_Malloc(vm->numStrings * sizeof(uint32_t), PU_LEVEL, NULL);

   for(uint32_t *itr = vm->strings, *end = itr + vm->numStrings; itr != end; ++itr)
   {
      tableIndex = SwapLong(*rover++);

      if (tableIndex < lumpLength)
         *itr = ACS_LoadStringACS0(data + tableIndex, data + lumpLength);
      else
         *itr = ACS_LoadStringACS0(data + lumpLength, data + lumpLength);
   }

   // The first part of the global string table must match VM-0 for compatibility.
   if(vm->id == 0 && ACSVM::GlobalNumStrings < vm->numStrings)
      vm->addStrings();

   // Read code.
   ACS_LoadScriptCodeACS0(vm, data, lumpLength, false);

   vm->loaded = true;
}
예제 #6
0
//
// Loads sectors
//
void UDMFParser::loadSectors(UDMFSetupSettings &setupSettings) const
{
   numsectors = (int)mSectors.getLength();
   sectors = estructalloctag(sector_t, numsectors, PU_LEVEL);

   for(int i = 0; i < numsectors; ++i)
   {
      sector_t *ss = sectors + i;
      const USector &us = mSectors[i];

      if(mNamespace == namespace_Eternity)
      {
         // These two pass the fixed_t value now
         ss->floorheight = us.heightfloor;
         ss->ceilingheight = us.heightceiling;

         // New to Eternity
         ss->floor_xoffs = us.xpanningfloor;
         ss->floor_yoffs = us.ypanningfloor;
         ss->ceiling_xoffs = us.xpanningceiling;
         ss->ceiling_yoffs = us.ypanningceiling;
         ss->floorbaseangle = static_cast<float>
            (E_NormalizeFlatAngle(us.rotationfloor) *  PI / 180.0f);
         ss->ceilingbaseangle = static_cast<float>
            (E_NormalizeFlatAngle(us.rotationceiling) *  PI / 180.0f);

         // Flags
         ss->flags |= us.secret ? SECF_SECRET : 0;

         // Friction: set the parameter directly from UDMF
         if(us.friction >= 0)   // default: -1
         {
            int friction, movefactor;
            P_CalcFriction(us.friction, friction, movefactor);

            ss->flags |= SECF_FRICTION;   // add the flag too
            ss->friction = friction;
            ss->movefactor = movefactor;
         }

         // Damage
         ss->damage = us.damageamount;
         ss->damagemask = us.damageinterval;
         ss->damagemod = E_DamageTypeNumForName(us.damagetype.constPtr());
         // If the following flags are true for the current sector, then set the
         // appropriate damageflags to true, otherwise don't set them.
         ss->damageflags |= us.damage_endgodmode ? SDMG_ENDGODMODE : 0;
         ss->damageflags |= us.damage_exitlevel ? SDMG_EXITLEVEL : 0;
         ss->damageflags |= us.damageterraineffect ? SDMG_TERRAINHIT : 0;
         ss->leakiness = eclamp(us.leakiness, 0, 256);

         // Terrain types
         if(us.floorterrain.strCaseCmp(DEFAULT_flat))
            ss->floorterrain = E_TerrainForName(us.floorterrain.constPtr());
         if (us.ceilingterrain.strCaseCmp(DEFAULT_flat))
            ss->ceilingterrain = E_TerrainForName(us.ceilingterrain.constPtr());

         // Lights
         ss->floorlightdelta = static_cast<int16_t>(us.lightfloor);
         ss->ceilinglightdelta = static_cast<int16_t>(us.lightceiling);
         ss->flags |=
         (us.lightfloorabsolute ? SECF_FLOORLIGHTABSOLUTE : 0) |
         (us.lightceilingabsolute ? SECF_CEILLIGHTABSOLUTE : 0);

         // sector colormaps
         ss->topmap = ss->midmap = ss->bottommap = -1; // mark as not specified

      }
      else
      {
         ss->floorheight = us.heightfloor << FRACBITS;
         ss->ceilingheight = us.heightceiling << FRACBITS;
      }
      ss->floorpic = R_FindFlat(us.texturefloor.constPtr());
      P_SetSectorCeilingPic(ss,
                            R_FindFlat(us.textureceiling.constPtr()));
      ss->lightlevel = us.lightlevel;
      ss->special = us.special;
      ss->tag = us.identifier;
      P_InitSector(ss);

      //
      // HERE GO THE PROPERTIES THAT MUST TAKE EFFECT AFTER P_InitSector
      //
      if(mNamespace == namespace_Eternity)
      {
         if(us.colormaptop.strCaseCmp(DEFAULT_default))
         {
            ss->topmap    = R_ColormapNumForName(us.colormaptop.constPtr());
            setupSettings.setSectorFlag(i, UDMF_SECTOR_INIT_COLORMAPPED);
         }
         if(us.colormapmid.strCaseCmp(DEFAULT_default))
         {
            ss->midmap    = R_ColormapNumForName(us.colormapmid.constPtr());
            setupSettings.setSectorFlag(i, UDMF_SECTOR_INIT_COLORMAPPED);
         }
         if(us.colormapbottom.strCaseCmp(DEFAULT_default))
         {
            ss->bottommap = R_ColormapNumForName(us.colormapbottom.constPtr());
            setupSettings.setSectorFlag(i, UDMF_SECTOR_INIT_COLORMAPPED);
         }

         // Portal fields
         // Floors
         ss->f_pflags |= us.portal_floor_alpha << PO_OPACITYSHIFT;
         ss->f_pflags |= us.portal_floor_blocksound ? PF_BLOCKSOUND : 0;
         ss->f_pflags |= us.portal_floor_disabled ? PF_DISABLED : 0;
         ss->f_pflags |= us.portal_floor_nopass ? PF_NOPASS : 0;
         ss->f_pflags |= us.portal_floor_norender ? PF_NORENDER : 0;
         if(!us.portal_floor_overlaytype.strCaseCmp(RENDERSTYLE_translucent))
            ss->f_pflags |= PS_OVERLAY;
         else if(!us.portal_floor_overlaytype.strCaseCmp(RENDERSTYLE_add))
            ss->f_pflags |= PS_OBLENDFLAGS; // PS_OBLENDFLAGS is PS_OVERLAY | PS_ADDITIVE
         ss->f_pflags |= us.portal_floor_useglobaltex ? PS_USEGLOBALTEX : 0;

         // Ceilings
         ss->c_pflags |= us.portal_ceil_alpha << PO_OPACITYSHIFT;
         ss->c_pflags |= us.portal_ceil_blocksound ? PF_BLOCKSOUND : 0;
         ss->c_pflags |= us.portal_ceil_disabled ? PF_DISABLED : 0;
         ss->c_pflags |= us.portal_ceil_nopass ? PF_NOPASS : 0;
         ss->c_pflags |= us.portal_ceil_norender ? PF_NORENDER : 0;
         if(!us.portal_ceil_overlaytype.strCaseCmp(RENDERSTYLE_translucent))
            ss->c_pflags |= PS_OVERLAY;
         else if(!us.portal_ceil_overlaytype.strCaseCmp(RENDERSTYLE_add))
            ss->c_pflags |= PS_OBLENDFLAGS; // PS_OBLENDFLAGS is PS_OVERLAY | PS_ADDITIVE
         ss->c_pflags |= us.portal_ceil_useglobaltex ? PS_USEGLOBALTEX : 0;
      }
   }
}
예제 #7
0
//
// Loads linedefs. Returns false on error.
//
bool UDMFParser::loadLinedefs()
{
   numlines = (int)mLinedefs.getLength();
   lines = estructalloctag(line_t, numlines, PU_LEVEL);
   for(int i = 0; i < numlines; ++i)
   {
      line_t *ld = lines + i;
      const ULinedef &uld = mLinedefs[i];
      if(uld.blocking)
         ld->flags |= ML_BLOCKING;
      if(uld.blockmonsters)
         ld->flags |= ML_BLOCKMONSTERS;
      if(uld.twosided)
         ld->flags |= ML_TWOSIDED;
      if(uld.dontpegtop)
         ld->flags |= ML_DONTPEGTOP;
      if(uld.dontpegbottom)
         ld->flags |= ML_DONTPEGBOTTOM;
      if(uld.secret)
         ld->flags |= ML_SECRET;
      if(uld.blocksound)
         ld->flags |= ML_SOUNDBLOCK;
      if(uld.dontdraw)
         ld->flags |= ML_DONTDRAW;
      if(uld.mapped)
         ld->flags |= ML_MAPPED;

      if(mNamespace == namespace_Doom || mNamespace == namespace_Eternity)
      {
         if(uld.passuse)
            ld->flags |= ML_PASSUSE;
      }

      // Eternity
      if(mNamespace == namespace_Eternity)
      {
         if(uld.midtex3d)
            ld->flags |= ML_3DMIDTEX;
         if(uld.firstsideonly)
            ld->extflags |= EX_ML_1SONLY;
         if(uld.blockeverything)
            ld->extflags |= EX_ML_BLOCKALL;
         if(uld.zoneboundary)
            ld->extflags |= EX_ML_ZONEBOUNDARY;
         if(uld.clipmidtex)
            ld->extflags |= EX_ML_CLIPMIDTEX;
         if(uld.midtex3dimpassible)
            ld->extflags |= EX_ML_3DMTPASSPROJ;
      }

      // TODO: Strife

      if(mNamespace == namespace_Hexen || mNamespace == namespace_Eternity)
      {
         if(uld.playercross)
            ld->extflags |= EX_ML_PLAYER | EX_ML_CROSS;
         if(uld.playeruse)
            ld->extflags |= EX_ML_PLAYER | EX_ML_USE;
         if(uld.monstercross)
            ld->extflags |= EX_ML_MONSTER | EX_ML_CROSS;
         if(uld.monsteruse)
            ld->extflags |= EX_ML_MONSTER | EX_ML_USE;
         if(uld.impact)
            ld->extflags |= EX_ML_MISSILE | EX_ML_IMPACT;
         if(uld.playerpush)
            ld->extflags |= EX_ML_PLAYER | EX_ML_PUSH;
         if(uld.monsterpush)
            ld->extflags |= EX_ML_MONSTER | EX_ML_PUSH;
         if(uld.missilecross)
            ld->extflags |= EX_ML_MISSILE | EX_ML_CROSS;
         if(uld.repeatspecial)
            ld->extflags |= EX_ML_REPEAT;
      }

      ld->special = uld.special;
      ld->tag = uld.identifier;
      ld->args[0] = uld.arg[0];
      ld->args[1] = uld.arg[1];
      ld->args[2] = uld.arg[2];
      ld->args[3] = uld.arg[3];
      ld->args[4] = uld.arg[4];
      if(uld.v1 < 0 || uld.v1 >= numvertexes ||
         uld.v2 < 0 || uld.v2 >= numvertexes ||
         uld.sidefront < 0 || uld.sidefront >= numsides ||
         uld.sideback < -1 || uld.sideback >= numsides)
      {
         mLine = uld.errorline;
         mColumn = 1;
         mError = "Vertex or sidedef overflow";
         return false;
      }
      ld->v1 = &vertexes[uld.v1];
      ld->v2 = &vertexes[uld.v2];
      ld->sidenum[0] = uld.sidefront;
      ld->sidenum[1] = uld.sideback;
      P_InitLineDef(ld);
      P_PostProcessLineFlags(ld);

      // more Eternity
      if(mNamespace == namespace_Eternity)
      {
         ld->alpha = uld.alpha;
         if(!uld.renderstyle.strCaseCmp(RENDERSTYLE_add))
            ld->extflags |= EX_ML_ADDITIVE;
         if(!uld.tranmap.empty())
         {
            if(uld.tranmap != "TRANMAP")
            {
               int special = W_CheckNumForName(uld.tranmap.constPtr());
               if(special < 0 || W_LumpLength(special) != 65536)
                  ld->tranlump = 0;
               else
                  ld->tranlump = special + 1;
            }
            else
               ld->tranlump = 0;
         }
      }
   }
   return true;
}
예제 #8
0
//
// Loads sidedefs
//
void UDMFParser::loadSidedefs() const
{
   numsides = (int)mSidedefs.getLength();
   sides = estructalloctag(side_t, numsides, PU_LEVEL);
}