Ejemplo n.º 1
0
static void CheatDebugFunc(player_t *player, cheat_t * cheat)
{
    char    lumpName[9];
    char    textBuffer[256];
    subsector_t *sub;

    if(!player->plr->mo || !usergame)
        return;

    P_GetMapLumpName(gameepisode, gamemap, lumpName);
    sprintf(textBuffer, "MAP [%s]  X:%5d  Y:%5d  Z:%5d",
            lumpName,
            player->plr->mo->pos[VX] >> FRACBITS,
            player->plr->mo->pos[VY] >> FRACBITS,
            player->plr->mo->pos[VZ] >> FRACBITS);
    P_SetMessage(player, textBuffer, false);

    // Also print some information to the console.
    Con_Message(textBuffer);
    sub = player->plr->mo->subsector;
    Con_Message("\nSubsector %i:\n", P_ToIndex(sub));
    Con_Message("  Floorz:%d pic:%d\n", P_GetIntp(sub, DMU_FLOOR_HEIGHT),
                P_GetIntp(sub, DMU_FLOOR_MATERIAL));
    Con_Message("  Ceilingz:%d pic:%d\n", P_GetIntp(sub, DMU_CEILING_HEIGHT),
                P_GetIntp(sub, DMU_CEILING_MATERIAL));
    Con_Message("Player height:%g   Player radius:%x\n",
                player->plr->mo->height, player->plr->mo->radius);
}
Ejemplo n.º 2
0
void P_CopySector(Sector *dest, Sector *src)
{
    xsector_t *xsrc = P_ToXSector(src);
    xsector_t *xdest = P_ToXSector(dest);

    if(src == dest)
        return; // no point copying self.

    // Copy the built-in properties.
    float ftemp[4];
    coord_t dtemp[2];

    P_SetFloatp  (dest, DMU_LIGHT_LEVEL,                P_GetFloatp(src, DMU_LIGHT_LEVEL));
    P_GetFloatpv (src,  DMU_COLOR,                      ftemp);
    P_SetFloatpv (dest, DMU_COLOR,                      ftemp);

    P_SetDoublep (dest, DMU_FLOOR_HEIGHT,               P_GetDoublep(src, DMU_FLOOR_HEIGHT));
    P_SetPtrp    (dest, DMU_FLOOR_MATERIAL,             P_GetPtrp(src, DMU_FLOOR_MATERIAL));
    P_GetFloatpv (src,  DMU_FLOOR_COLOR,                ftemp);
    P_SetFloatpv (dest, DMU_FLOOR_COLOR,                ftemp);
    P_GetDoublepv(src,  DMU_FLOOR_MATERIAL_OFFSET_XY,   dtemp);
    P_SetDoublepv(dest, DMU_FLOOR_MATERIAL_OFFSET_XY,   dtemp);
    P_SetIntp    (dest, DMU_FLOOR_SPEED,                P_GetIntp(src, DMU_FLOOR_SPEED));
    P_SetDoublep (dest, DMU_FLOOR_TARGET_HEIGHT,        P_GetFloatp(src, DMU_FLOOR_TARGET_HEIGHT));

    P_SetDoublep (dest, DMU_CEILING_HEIGHT,             P_GetDoublep(src, DMU_CEILING_HEIGHT));
    P_SetPtrp    (dest, DMU_CEILING_MATERIAL,           P_GetPtrp(src, DMU_CEILING_MATERIAL));
    P_GetFloatpv (src,  DMU_CEILING_COLOR,              ftemp);
    P_SetFloatpv (dest, DMU_CEILING_COLOR,              ftemp);
    P_GetDoublepv(src,  DMU_CEILING_MATERIAL_OFFSET_XY, dtemp);
    P_SetDoublepv(dest, DMU_CEILING_MATERIAL_OFFSET_XY, dtemp);
    P_SetIntp    (dest, DMU_CEILING_SPEED,              P_GetIntp(src, DMU_CEILING_SPEED));
    P_SetDoublep (dest, DMU_CEILING_TARGET_HEIGHT,      P_GetFloatp(src, DMU_CEILING_TARGET_HEIGHT));

    // Copy the extended properties too
#if __JDOOM__ || __JHERETIC__ || __JDOOM64__
    xdest->special = xsrc->special;
    xdest->soundTraversed = xsrc->soundTraversed;
    xdest->soundTarget = xsrc->soundTarget;
#if __JHERETIC__
    xdest->seqType = xsrc->seqType;
#endif
    xdest->SP_floororigheight = xsrc->SP_floororigheight;
    xdest->SP_ceilorigheight = xsrc->SP_ceilorigheight;
    xdest->origLight = xsrc->origLight;
    std::memcpy(xdest->origRGB, xsrc->origRGB, sizeof(float) * 3);
    if(xsrc->xg && xdest->xg)
        std::memcpy(xdest->xg, xsrc->xg, sizeof(*xdest->xg));
    else
        xdest->xg = 0;
#else
    xdest->special = xsrc->special;
    xdest->soundTraversed = xsrc->soundTraversed;
    xdest->soundTarget = xsrc->soundTarget;
    xdest->seqType = xsrc->seqType;
#endif
}
Ejemplo n.º 3
0
void EV_TurnTagLightsOff(linedef_t *line)
{
    int         j;
    float       min;
    float       lightlevel;
    sector_t   *sec = NULL, *tsec;
    linedef_t     *other;
    iterlist_t *list;

    list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false);
    if(!list)
        return;

    P_IterListResetIterator(list, true);
    while((sec = P_IterListIterator(list)) != NULL)
    {
        min = P_GetFloatp(sec, DMU_LIGHT_LEVEL);
        for(j = 0; j < P_GetIntp(sec, DMU_LINEDEF_COUNT); ++j)
        {
            other = P_GetPtrp(sec, DMU_LINEDEF_OF_SECTOR | j);
            tsec = P_GetNextSector(other, sec);

            if(!tsec)
                continue;

            lightlevel = P_GetFloatp(tsec, DMU_LIGHT_LEVEL);

            if(lightlevel < min)
                min = lightlevel;
        }

        P_SetFloatp(sec, DMU_LIGHT_LEVEL, min);
    }
}
Ejemplo n.º 4
0
void P_CopyLine(Line *dest, Line *src)
{
    xline_t *xsrc  = P_ToXLine(src);
    xline_t *xdest = P_ToXLine(dest);

    if(src == dest)
        return; // no point copying self

    // Copy the built-in properties
    for(int i = 0; i < 2; ++i) // For each side
    {
        int sidx = (i==0? DMU_FRONT : DMU_BACK);

        Side *sidefrom = (Side *)P_GetPtrp(src, sidx);
        Side *sideto = (Side *)P_GetPtrp(dest, sidx);

        if(!sidefrom || !sideto)
            continue;

        float temp[4];
        coord_t itemp[2];

        P_SetPtrp    (sideto,   DMU_TOP_MATERIAL,               P_GetPtrp(sidefrom, DMU_TOP_MATERIAL));
        P_GetDoublepv(sidefrom, DMU_TOP_MATERIAL_OFFSET_XY,     itemp);
        P_SetDoublepv(sideto,   DMU_TOP_MATERIAL_OFFSET_XY,     itemp);
        P_GetFloatpv (sidefrom, DMU_TOP_COLOR,                  temp);
        P_SetFloatpv (sideto,   DMU_TOP_COLOR,                  temp);

        P_SetPtrp    (sideto,   DMU_MIDDLE_MATERIAL,            P_GetPtrp(sidefrom, DMU_MIDDLE_MATERIAL));
        P_GetDoublepv(sidefrom, DMU_MIDDLE_MATERIAL_OFFSET_XY,  itemp);
        P_SetDoublepv(sideto,   DMU_MIDDLE_MATERIAL_OFFSET_XY,  itemp);
        P_SetFloatpv (sideto,   DMU_MIDDLE_COLOR,               temp);
        P_SetIntp    (sideto,   DMU_MIDDLE_BLENDMODE,           P_GetIntp(sidefrom, DMU_MIDDLE_BLENDMODE));

        P_SetPtrp    (sideto,   DMU_BOTTOM_MATERIAL,            P_GetPtrp(sidefrom, DMU_BOTTOM_MATERIAL));
        P_GetDoublepv(sidefrom, DMU_BOTTOM_MATERIAL_OFFSET_XY,  itemp);
        P_SetDoublepv(sideto,   DMU_BOTTOM_MATERIAL_OFFSET_XY,  itemp);
        P_GetFloatpv (sidefrom, DMU_BOTTOM_COLOR,               temp);
        P_SetFloatpv (sideto,   DMU_BOTTOM_COLOR,               temp);
    }

    // Copy the extended properties too
#if __JDOOM__ || __JHERETIC__ || __JDOOM64__
    xdest->special = xsrc->special;
    xdest->tag     = xsrc->tag;
    if(xsrc->xg && xdest->xg)
        std::memcpy(xdest->xg, xsrc->xg, sizeof(*xdest->xg));
    else
        xdest->xg = 0;
#else
    xdest->special = xsrc->special;
    xdest->arg1 = xsrc->arg1;
    xdest->arg2 = xsrc->arg2;
    xdest->arg3 = xsrc->arg3;
    xdest->arg4 = xsrc->arg4;
    xdest->arg5 = xsrc->arg5;
#endif
}
Ejemplo n.º 5
0
void P_RecursiveSound(struct mobj_s* soundTarget, Sector* sec, int soundBlocks)
{
    spreadsoundtoneighborsparams_t params;
    xsector_t* xsec = P_ToXSector(sec);

    // Wake up all monsters in this sector.
    if(P_GetIntp(sec, DMU_VALID_COUNT) == VALIDCOUNT && xsec->soundTraversed <= soundBlocks + 1)
        return; // Already flooded.

    P_SetIntp(sec, DMU_VALID_COUNT, VALIDCOUNT);
    xsec->soundTraversed = soundBlocks + 1;
    xsec->soundTarget = soundTarget;

    params.baseSec = sec;
    params.soundBlocks = soundBlocks;
    params.soundTarget = soundTarget;
    P_Iteratep(sec, DMU_LINE, &params, spreadSoundToNeighbors);
}
Ejemplo n.º 6
0
void EV_LightTurnOn(linedef_t *line, float max)
{
    int         j;
    float       lightlevel;
    sector_t   *sec = NULL, *tsec;
    linedef_t     *tline;
    iterlist_t *list;

    list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false);
    if(!list)
        return;

    P_IterListResetIterator(list, true);
    while((sec = P_IterListIterator(list)) != NULL)
    {
        // max = 0 means to search
        // for highest light level
        // surrounding sector
        if(!max)
        {
            for(j = 0; j < P_GetIntp(sec, DMU_LINEDEF_COUNT); ++j)
            {
                tline = P_GetPtrp(sec, DMU_LINEDEF_OF_SECTOR | j);
                tsec = P_GetNextSector(tline, sec);

                if(!tsec)
                    continue;

                lightlevel = P_GetFloatp(tsec, DMU_LIGHT_LEVEL);

                if(lightlevel > max)
                    max = lightlevel;
            }
        }
        P_SetFloatp(sec, DMU_LIGHT_LEVEL, max);
    }
}
Ejemplo n.º 7
0
/**
 * Reads all versions of archived lines.
 * Including the old Ver1.
 */
void SV_ReadLine(Line *li, MapStateReader *msr)
{
    xline_t *xli   = P_ToXLine(li);
    Reader1 *reader = msr->reader();
    int mapVersion = msr->mapVersion();

    bool xgDataFollows = false;
#if __JHEXEN__
    if(mapVersion >= 4)
#else
    if(mapVersion >= 2)
#endif
    {
        xgDataFollows = Reader_ReadByte(reader) == 1;
    }
#ifdef __JHEXEN__
    DENG2_UNUSED(xgDataFollows);
#endif

    // A version byte?
    int ver = 1;
#if __JHEXEN__
    if(mapVersion >= 3)
#else
    if(mapVersion >= 5)
#endif
    {
        ver = (int) Reader_ReadByte(reader);
    }

    if(ver >= 4)
    {
        P_SetIntp(li, DMU_FLAGS, Reader_ReadInt16(reader));
    }

    int flags = Reader_ReadInt16(reader);
    if(xli->flags & ML_TWOSIDED)
    {
        flags |= ML_TWOSIDED;
    }

    if(ver < 4)
    {
        // Translate old line flags.
        int ddLineFlags = 0;

        if(flags & 0x0001) // old ML_BLOCKING flag
        {
            ddLineFlags |= DDLF_BLOCKING;
            flags &= ~0x0001;
        }

        if(flags & 0x0008) // old ML_DONTPEGTOP flag
        {
            ddLineFlags |= DDLF_DONTPEGTOP;
            flags &= ~0x0008;
        }

        if(flags & 0x0010) // old ML_DONTPEGBOTTOM flag
        {
            ddLineFlags |= DDLF_DONTPEGBOTTOM;
            flags &= ~0x0010;
        }

        P_SetIntp(li, DMU_FLAGS, ddLineFlags);
    }

    if(ver < 3)
    {
        if(flags & ML_MAPPED)
        {
            int lineIDX = P_ToIndex(li);

            // Set line as having been seen by all players..
            de::zap(xli->mapped);
            for(int i = 0; i < MAXPLAYERS; ++i)
            {
                P_SetLineAutomapVisibility(i, lineIDX, true);
            }
        }
    }

    xli->flags = flags;

    if(ver >= 3)
    {
        for(int i = 0; i < MAXPLAYERS; ++i)
        {
            xli->mapped[i] = Reader_ReadByte(reader);
        }
    }

#if __JHEXEN__
    xli->special = Reader_ReadByte(reader);
    xli->arg1    = Reader_ReadByte(reader);
    xli->arg2    = Reader_ReadByte(reader);
    xli->arg3    = Reader_ReadByte(reader);
    xli->arg4    = Reader_ReadByte(reader);
    xli->arg5    = Reader_ReadByte(reader);
#else
    xli->special = Reader_ReadInt16(reader);
    /*xli->tag     =*/ Reader_ReadInt16(reader);
#endif

    // For each side
    for(int i = 0; i < 2; ++i)
    {
        Side *si = (Side *)P_GetPtrp(li, (i? DMU_BACK:DMU_FRONT));
        if(!si) continue;

        // Versions latter than 2 store per surface texture offsets.
        if(ver >= 2)
        {
            float offset[2];

            offset[VX] = (float) Reader_ReadInt16(reader);
            offset[VY] = (float) Reader_ReadInt16(reader);
            P_SetFloatpv(si, DMU_TOP_MATERIAL_OFFSET_XY, offset);

            offset[VX] = (float) Reader_ReadInt16(reader);
            offset[VY] = (float) Reader_ReadInt16(reader);
            P_SetFloatpv(si, DMU_MIDDLE_MATERIAL_OFFSET_XY, offset);

            offset[VX] = (float) Reader_ReadInt16(reader);
            offset[VY] = (float) Reader_ReadInt16(reader);
            P_SetFloatpv(si, DMU_BOTTOM_MATERIAL_OFFSET_XY, offset);
        }
        else
        {
            float offset[2];

            offset[VX] = (float) Reader_ReadInt16(reader);
            offset[VY] = (float) Reader_ReadInt16(reader);

            P_SetFloatpv(si, DMU_TOP_MATERIAL_OFFSET_XY,    offset);
            P_SetFloatpv(si, DMU_MIDDLE_MATERIAL_OFFSET_XY, offset);
            P_SetFloatpv(si, DMU_BOTTOM_MATERIAL_OFFSET_XY, offset);
        }

        if(ver >= 3)
        {
            P_SetIntp(si, DMU_TOP_FLAGS,    Reader_ReadInt16(reader));
            P_SetIntp(si, DMU_MIDDLE_FLAGS, Reader_ReadInt16(reader));
            P_SetIntp(si, DMU_BOTTOM_FLAGS, Reader_ReadInt16(reader));
        }

        world_Material *topMaterial = 0, *bottomMaterial = 0, *middleMaterial = 0;

#if !__JHEXEN__
        if(mapVersion >= 4)
#endif
        {
            topMaterial    = msr->material(Reader_ReadInt16(reader), 1);
            bottomMaterial = msr->material(Reader_ReadInt16(reader), 1);
            middleMaterial = msr->material(Reader_ReadInt16(reader), 1);
        }

        P_SetPtrp(si, DMU_TOP_MATERIAL,    topMaterial);
        P_SetPtrp(si, DMU_BOTTOM_MATERIAL, bottomMaterial);
        P_SetPtrp(si, DMU_MIDDLE_MATERIAL, middleMaterial);

        // Ver2 includes surface colours
        if(ver >= 2)
        {
            float rgba[4];
            int flags;

            for(int k = 0; k < 3; ++k)
                rgba[k] = (float) Reader_ReadByte(reader) / 255.f;
            rgba[3] = 1;
            P_SetFloatpv(si, DMU_TOP_COLOR, rgba);

            for(int k = 0; k < 3; ++k)
                rgba[k] = (float) Reader_ReadByte(reader) / 255.f;
            rgba[3] = 1;
            P_SetFloatpv(si, DMU_BOTTOM_COLOR, rgba);

            for(int k = 0; k < 4; ++k)
                rgba[k] = (float) Reader_ReadByte(reader) / 255.f;
            P_SetFloatpv(si, DMU_MIDDLE_COLOR, rgba);

            P_SetIntp(si, DMU_MIDDLE_BLENDMODE, Reader_ReadInt32(reader));

            flags = Reader_ReadInt16(reader);

            if(mapVersion < 12)
            {
                if(P_GetIntp(si, DMU_FLAGS) & SDF_SUPPRESS_BACK_SECTOR)
                    flags |= SDF_SUPPRESS_BACK_SECTOR;
            }
            P_SetIntp(si, DMU_FLAGS, flags);
        }
    }

#if !__JHEXEN__
    if(xgDataFollows)
    {
        SV_ReadXGLine(li, msr);
    }
#endif
}
Ejemplo n.º 8
0
void SV_WriteLine(Line *li, MapStateWriter *msw)
{
    xline_t *xli   = P_ToXLine(li);
    Writer1 *writer = msw->writer();

#if !__JHEXEN__
    Writer_WriteByte(writer, xli->xg? 1 : 0); /// @c 1= XG data will follow.
#else
    Writer_WriteByte(writer, 0);
#endif

    // Version.
    // 2: Per surface texture offsets.
    // 2: Surface colors.
    // 3: "Mapped by player" values.
    // 3: Surface flags.
    // 4: Engine-side line flags.
    Writer_WriteByte(writer, 4); // Write a version byte

    Writer_WriteInt16(writer, P_GetIntp(li, DMU_FLAGS));
    Writer_WriteInt16(writer, xli->flags);

    for(int i = 0; i < MAXPLAYERS; ++i)
        Writer_WriteByte(writer, xli->mapped[i]);

#if __JHEXEN__
    Writer_WriteByte(writer, xli->special);
    Writer_WriteByte(writer, xli->arg1);
    Writer_WriteByte(writer, xli->arg2);
    Writer_WriteByte(writer, xli->arg3);
    Writer_WriteByte(writer, xli->arg4);
    Writer_WriteByte(writer, xli->arg5);
#else
    Writer_WriteInt16(writer, xli->special);
    Writer_WriteInt16(writer, xli->tag);
#endif

    // For each side
    float rgba[4];
    for(int i = 0; i < 2; ++i)
    {
        Side *si = (Side *)P_GetPtrp(li, (i? DMU_BACK:DMU_FRONT));
        if(!si) continue;

        Writer_WriteInt16(writer, P_GetIntp(si, DMU_TOP_MATERIAL_OFFSET_X));
        Writer_WriteInt16(writer, P_GetIntp(si, DMU_TOP_MATERIAL_OFFSET_Y));
        Writer_WriteInt16(writer, P_GetIntp(si, DMU_MIDDLE_MATERIAL_OFFSET_X));
        Writer_WriteInt16(writer, P_GetIntp(si, DMU_MIDDLE_MATERIAL_OFFSET_Y));
        Writer_WriteInt16(writer, P_GetIntp(si, DMU_BOTTOM_MATERIAL_OFFSET_X));
        Writer_WriteInt16(writer, P_GetIntp(si, DMU_BOTTOM_MATERIAL_OFFSET_Y));

        Writer_WriteInt16(writer, P_GetIntp(si, DMU_TOP_FLAGS));
        Writer_WriteInt16(writer, P_GetIntp(si, DMU_MIDDLE_FLAGS));
        Writer_WriteInt16(writer, P_GetIntp(si, DMU_BOTTOM_FLAGS));

        Writer_WriteInt16(writer, msw->serialIdFor((world_Material *)P_GetPtrp(si, DMU_TOP_MATERIAL)));
        Writer_WriteInt16(writer, msw->serialIdFor((world_Material *)P_GetPtrp(si, DMU_BOTTOM_MATERIAL)));
        Writer_WriteInt16(writer, msw->serialIdFor((world_Material *)P_GetPtrp(si, DMU_MIDDLE_MATERIAL)));

        P_GetFloatpv(si, DMU_TOP_COLOR, rgba);
        for(int k = 0; k < 3; ++k)
            Writer_WriteByte(writer, (byte)(255 * rgba[k]));

        P_GetFloatpv(si, DMU_BOTTOM_COLOR, rgba);
        for(int k = 0; k < 3; ++k)
            Writer_WriteByte(writer, (byte)(255 * rgba[k]));

        P_GetFloatpv(si, DMU_MIDDLE_COLOR, rgba);
        for(int k = 0; k < 4; ++k)
            Writer_WriteByte(writer, (byte)(255 * rgba[k]));

        Writer_WriteInt32(writer, P_GetIntp(si, DMU_MIDDLE_BLENDMODE));
        Writer_WriteInt16(writer, P_GetIntp(si, DMU_FLAGS));
    }

#if !__JHEXEN__
    // Extended General?
    if(xli->xg)
    {
        SV_WriteXGLine(li, msw);
    }
#endif
}
Ejemplo n.º 9
0
void SV_WriteSector(Sector *sec, MapStateWriter *msw)
{
    Writer1 *writer = msw->writer();

    int i, type;
    float flooroffx           = P_GetFloatp(sec, DMU_FLOOR_MATERIAL_OFFSET_X);
    float flooroffy           = P_GetFloatp(sec, DMU_FLOOR_MATERIAL_OFFSET_Y);
    float ceiloffx            = P_GetFloatp(sec, DMU_CEILING_MATERIAL_OFFSET_X);
    float ceiloffy            = P_GetFloatp(sec, DMU_CEILING_MATERIAL_OFFSET_Y);
    byte lightlevel           = (byte) (255.f * P_GetFloatp(sec, DMU_LIGHT_LEVEL));
    short floorheight         = (short) P_GetIntp(sec, DMU_FLOOR_HEIGHT);
    short ceilingheight       = (short) P_GetIntp(sec, DMU_CEILING_HEIGHT);
    short floorFlags          = (short) P_GetIntp(sec, DMU_FLOOR_FLAGS);
    short ceilingFlags        = (short) P_GetIntp(sec, DMU_CEILING_FLAGS);
    world_Material *floorMaterial   = (world_Material *)P_GetPtrp(sec, DMU_FLOOR_MATERIAL);
    world_Material *ceilingMaterial = (world_Material *)P_GetPtrp(sec, DMU_CEILING_MATERIAL);

    xsector_t *xsec = P_ToXSector(sec);

#if !__JHEXEN__
    // Determine type.
    if(xsec->xg)
        type = sc_xg1;
    else
#endif
        if(NON_ZERO(flooroffx) || NON_ZERO(flooroffy) || NON_ZERO(ceiloffx) || NON_ZERO(ceiloffy))
        type = sc_ploff;
    else
        type = sc_normal;

    // Type byte.
    Writer_WriteByte(writer, type);

    // Version.
    // 2: Surface colors.
    // 3: Surface flags.
    Writer_WriteByte(writer, 3); // write a version byte.

    Writer_WriteInt16(writer, floorheight);
    Writer_WriteInt16(writer, ceilingheight);
    Writer_WriteInt16(writer, msw->serialIdFor(floorMaterial));
    Writer_WriteInt16(writer, msw->serialIdFor(ceilingMaterial));
    Writer_WriteInt16(writer, floorFlags);
    Writer_WriteInt16(writer, ceilingFlags);
#if __JHEXEN__
    Writer_WriteInt16(writer, (short) lightlevel);
#else
    Writer_WriteByte(writer, lightlevel);
#endif

    float rgb[3];
    P_GetFloatpv(sec, DMU_COLOR, rgb);
    for(i = 0; i < 3; ++i)
        Writer_WriteByte(writer, (byte)(255.f * rgb[i]));

    P_GetFloatpv(sec, DMU_FLOOR_COLOR, rgb);
    for(i = 0; i < 3; ++i)
        Writer_WriteByte(writer, (byte)(255.f * rgb[i]));

    P_GetFloatpv(sec, DMU_CEILING_COLOR, rgb);
    for(i = 0; i < 3; ++i)
        Writer_WriteByte(writer, (byte)(255.f * rgb[i]));

    Writer_WriteInt16(writer, xsec->special);
    Writer_WriteInt16(writer, xsec->tag);

#if __JHEXEN__
    Writer_WriteInt16(writer, xsec->seqType);
#endif

    if(type == sc_ploff
#if !__JHEXEN__
       || type == sc_xg1
#endif
       )
    {
        Writer_WriteFloat(writer, flooroffx);
        Writer_WriteFloat(writer, flooroffy);
        Writer_WriteFloat(writer, ceiloffx);
        Writer_WriteFloat(writer, ceiloffy);
    }

#if !__JHEXEN__
    if(xsec->xg) // Extended General?
    {
        SV_WriteXGSector(sec, writer);
    }
#endif
}