Example #1
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
}
Example #2
0
int findNextPlaneHeight(void* ptr, void* context)
{
    findnextplaneheightparams_t* params = (findnextplaneheightparams_t*) context;
    Sector* other = P_GetNextSector((Line*) ptr, params->baseSec);
    coord_t otherHeight;

    if(!other)
        return false; // Continue iteration.

    otherHeight = P_GetDoublep(other, ((params->flags & FNPHF_FLOOR)? DMU_FLOOR_HEIGHT : DMU_CEILING_HEIGHT));
    if(params->flags & FNPHF_ABOVE)
    {
        if(otherHeight < params->val && otherHeight > params->baseHeight)
        {
            params->val = otherHeight;
            params->foundSec = other;
        }
    }
    else if(otherHeight > params->val && otherHeight < params->baseHeight)
    {
        params->val = otherHeight;
        params->foundSec = other;
    }
    return false; // Continue iteration.
}
Example #3
0
int findExtremalPlaneHeight(void* ptr, void* context)
{
    findextremalplaneheightparams_t* params = (findextremalplaneheightparams_t*) context;
    Sector* other = P_GetNextSector((Line*) ptr, params->baseSec);
    coord_t height;

    if(!other)
        return false; // Continue iteration.

    height = P_GetDoublep(other, ((params->flags & FEPHF_FLOOR)? DMU_FLOOR_HEIGHT : DMU_CEILING_HEIGHT));
    if(params->flags & FEPHF_MIN)
    {
        if(height < params->val)
        {
            params->val = height;
            params->foundSec = other;
        }
    }
    else if(height > params->val)
    {
        params->val = height;
        params->foundSec = other;
    }

    return false; // Continue iteration.
}
Example #4
0
/**
 * Called every tic frame that the player origin is in a special sector
 */
void P_PlayerInSpecialSector(player_t *player)
{
    Sector *sector = Mobj_Sector(player->plr->mo);

    if(IS_CLIENT) return;

    // Falling, not all the way down yet?
    if(!FEQUAL(player->plr->mo->origin[VZ], P_GetDoublep(sector, DMU_FLOOR_HEIGHT))) return;

    // Has hitten ground.
    switch(P_ToXSector(sector)->special)
    {
    default:
        break;

    case 5: ///< HELLSLIME DAMAGE
        if(!player->powers[PT_IRONFEET])
            if(!(mapTime & 0x1f))
                P_DamageMobj(player->plr->mo, NULL, NULL, 10, false);
        break;

    case 7: ///< NUKAGE DAMAGE
        if(!player->powers[PT_IRONFEET])
            if(!(mapTime & 0x1f))
                P_DamageMobj(player->plr->mo, NULL, NULL, 5, false);
        break;

    case 16: ///< SUPER HELLSLIME DAMAGE
    case 4:  ///< STROBE HURT
        if(!player->powers[PT_IRONFEET] || (P_Random() < 5))
        {
            if(!(mapTime & 0x1f))
                P_DamageMobj(player->plr->mo, NULL, NULL, 20, false);
        }
        break;

    case 9: ///< SECRET SECTOR
        player->secretCount++;
        P_ToXSector(sector)->special = 0;
        if(cfg.secretMsg)
        {
            P_SetMessage(player, "You've found a secret area!");
            // S_ConsoleSound(SFX_SECRET, 0, player - players); // jd64
        }
        break;
    }
}
Example #5
0
dd_bool EV_StartFloorWaggle(int tag, int height, int speed, int offset, int timer)
{
    iterlist_t *list = P_GetSectorIterListForTag(tag, false);
    if(!list) return false;

    dd_bool retCode = false;

    IterList_SetIteratorDirection(list, ITERLIST_FORWARD);
    IterList_RewindIterator(list);

    Sector *sec;
    while((sec = (Sector *)IterList_MoveIterator(list)))
    {
        if(P_ToXSector(sec)->specialData)
            continue; // Already moving, so keep going...

        retCode = true;

        waggle_t *waggle = (waggle_t *)Z_Calloc(sizeof(*waggle), PU_MAP, 0);
        waggle->thinker.function = (thinkfunc_t) T_FloorWaggle;
        Thinker_Add(&waggle->thinker);

        P_ToXSector(sec)->specialData = waggle;
        waggle->sector         = sec;
        waggle->originalHeight = P_GetDoublep(sec, DMU_FLOOR_HEIGHT);
        waggle->accumulator    = offset;
        waggle->accDelta       = FIX2FLT(speed << 10);
        waggle->scale          = 0;
        waggle->targetScale    = FIX2FLT(height << 10);
        waggle->scaleDelta     =
            FIX2FLT(FLT2FIX(waggle->targetScale) /
                    (TICSPERSEC + ((3 * TICSPERSEC) * height) / 255));
        waggle->ticker         = timer ? timer * 35 : -1;
        waggle->state          = WS_EXPAND;
    }

    return retCode;
}
Example #6
0
int EV_OpenPillar(Line * /*line*/, byte *args)
{
    iterlist_t *list = P_GetSectorIterListForTag((int) args[0], false);
    if(!list) return 0;

    int rtn = 0;

    IterList_SetIteratorDirection(list, ITERLIST_FORWARD);
    IterList_RewindIterator(list);

    Sector *sec;
    while((sec = (Sector *)IterList_MoveIterator(list)))
    {
        // If already moving keep going...
        if(P_ToXSector(sec)->specialData)
            continue;

        if(!FEQUAL(P_GetDoublep(sec, DMU_FLOOR_HEIGHT),
                   P_GetDoublep(sec, DMU_CEILING_HEIGHT)))
            continue; // Pillar isn't closed.

        rtn = 1;

        pillar_t *pillar = (pillar_t *)Z_Calloc(sizeof(*pillar), PU_MAP, 0);
        pillar->thinker.function = (thinkfunc_t) T_BuildPillar;
        Thinker_Add(&pillar->thinker);

        P_ToXSector(sec)->specialData = pillar;
        pillar->sector = sec;
        if(!args[2])
        {
            P_FindSectorSurroundingLowestFloor(sec,
                P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &pillar->floorDest);
        }
        else
        {
            pillar->floorDest =
                P_GetDoublep(sec, DMU_FLOOR_HEIGHT) - (coord_t) args[2];
        }

        if(!args[3])
        {
            P_FindSectorSurroundingHighestCeiling(sec, 0, &pillar->ceilingDest);
        }
        else
        {
            pillar->ceilingDest =
                P_GetDoublep(sec, DMU_CEILING_HEIGHT) + (coord_t) args[3];
        }

        if(P_GetDoublep(sec, DMU_FLOOR_HEIGHT) - pillar->floorDest >=
           pillar->ceilingDest - P_GetDoublep(sec, DMU_CEILING_HEIGHT))
        {
            pillar->floorSpeed = (float) args[1] * (1.0f / 8);
            pillar->ceilingSpeed =
                (P_GetDoublep(sec, DMU_CEILING_HEIGHT) - pillar->ceilingDest) *
                    (pillar->floorSpeed / (pillar->floorDest - P_GetDoublep(sec, DMU_FLOOR_HEIGHT)));
        }
        else
        {
            pillar->ceilingSpeed = (float) args[1] * (1.0f / 8);
            pillar->floorSpeed =
                (pillar->floorDest - P_GetDoublep(sec, DMU_FLOOR_HEIGHT)) *
                    (pillar->ceilingSpeed / (P_GetDoublep(sec, DMU_CEILING_HEIGHT) - pillar->ceilingDest));
        }

        pillar->direction = -1; // Open the pillar.
        SN_StartSequence((mobj_t *)P_GetPtrp(pillar->sector, DMU_EMITTER),
                         SEQ_PLATFORM + P_ToXSector(pillar->sector)->seqType);
    }

    return rtn;
}
Example #7
0
int EV_BuildPillar(Line * /*line*/, byte *args, dd_bool crush)
{
    iterlist_t *list = P_GetSectorIterListForTag((int) args[0], false);
    if(!list) return 0;

    int rtn = 0;

    IterList_SetIteratorDirection(list, ITERLIST_FORWARD);
    IterList_RewindIterator(list);

    Sector *sec;
    while((sec = (Sector *)IterList_MoveIterator(list)))
    {
        // If already moving keep going...
        if(P_ToXSector(sec)->specialData)
            continue;

        if(FEQUAL(P_GetDoublep(sec, DMU_FLOOR_HEIGHT),
                  P_GetDoublep(sec, DMU_CEILING_HEIGHT)))
            continue; // Pillar is already closed.

        rtn = 1;
        coord_t newHeight = 0;
        if(!args[2])
        {
            newHeight = P_GetDoublep(sec, DMU_FLOOR_HEIGHT) +
                ((P_GetDoublep(sec, DMU_CEILING_HEIGHT) -
                  P_GetDoublep(sec, DMU_FLOOR_HEIGHT)) * .5f);
        }
        else
        {
            newHeight = P_GetDoublep(sec, DMU_FLOOR_HEIGHT) + (coord_t) args[2];
        }

        pillar_t *pillar = (pillar_t *)Z_Calloc(sizeof(*pillar), PU_MAP, 0);
        pillar->thinker.function = (thinkfunc_t) T_BuildPillar;
        Thinker_Add(&pillar->thinker);

        P_ToXSector(sec)->specialData = pillar;
        pillar->sector = sec;

        if(!args[2])
        {
            pillar->ceilingSpeed = pillar->floorSpeed =
                (float) args[1] * (1.0f / 8);
        }
        else if(newHeight - P_GetDoublep(sec, DMU_FLOOR_HEIGHT) >
                P_GetDoublep(sec, DMU_CEILING_HEIGHT) - newHeight)
        {
            pillar->floorSpeed = (float) args[1] * (1.0f / 8);
            pillar->ceilingSpeed =
                (P_GetDoublep(sec, DMU_CEILING_HEIGHT) - newHeight) *
                      (pillar->floorSpeed / (newHeight - P_GetDoublep(sec, DMU_FLOOR_HEIGHT)));
        }
        else
        {
            pillar->ceilingSpeed = (float) args[1] * (1.0f / 8);
            pillar->floorSpeed =
                (newHeight - P_GetDoublep(sec, DMU_FLOOR_HEIGHT)) *
                    (pillar->ceilingSpeed / (P_GetDoublep(sec, DMU_CEILING_HEIGHT) - newHeight));
        }

        pillar->floorDest = newHeight;
        pillar->ceilingDest = newHeight;
        pillar->direction = 1;
        pillar->crush = crush * (int) args[3];
        SN_StartSequence((mobj_t *)P_GetPtrp(pillar->sector, DMU_EMITTER),
                         SEQ_PLATFORM + P_ToXSector(pillar->sector)->seqType);
    }
    return rtn;
}
Example #8
0
static void SV_v13_ReadMobj(void)
{
    coord_t pos[3], mom[3], floorz, ceilingz, radius, height;
    int frame, valid, type, ddflags = 0;
    spritenum_t sprite;
    mobjinfo_t* info;
    angle_t angle;
    mobj_t* mo;

    // The thinker was 3 ints long.
    Reader_ReadInt32(svReader);
    Reader_ReadInt32(svReader);
    Reader_ReadInt32(svReader);

    pos[VX] = FIX2FLT(Reader_ReadInt32(svReader));
    pos[VY] = FIX2FLT(Reader_ReadInt32(svReader));
    pos[VZ] = FIX2FLT(Reader_ReadInt32(svReader));

    // Sector links.
    Reader_ReadInt32(svReader);
    Reader_ReadInt32(svReader);

    angle = (angle_t) (ANG45 * (Reader_ReadInt32(svReader) / 45));
    sprite = Reader_ReadInt32(svReader);
    frame = Reader_ReadInt32(svReader);
    frame &= ~FF_FRAMEMASK; // not used anymore.

    // Block links.
    Reader_ReadInt32(svReader);
    Reader_ReadInt32(svReader);

    // BspLeaf.
    Reader_ReadInt32(svReader);

    floorz   = FIX2FLT(Reader_ReadInt32(svReader));
    ceilingz = FIX2FLT(Reader_ReadInt32(svReader));
    radius   = FIX2FLT(Reader_ReadInt32(svReader));
    height   = FIX2FLT(Reader_ReadInt32(svReader));
    mom[MX]  = FIX2FLT(Reader_ReadInt32(svReader));
    mom[MY]  = FIX2FLT(Reader_ReadInt32(svReader));
    mom[MZ]  = FIX2FLT(Reader_ReadInt32(svReader));
    valid    = Reader_ReadInt32(svReader);
    type     = Reader_ReadInt32(svReader);

    info = &MOBJINFO[type];

    if(info->flags & MF_SOLID)
        ddflags |= DDMF_SOLID;
    if(info->flags2 & MF2_DONTDRAW)
        ddflags |= DDMF_DONTDRAW;

    /**
     * We now have all the information we need to create the mobj.
     */
    mo = P_MobjCreateXYZ(P_MobjThinker, pos[VX], pos[VY], pos[VZ], angle,
                         radius, height, ddflags);

    mo->sprite  = sprite;
    mo->frame   = frame;
    mo->floorZ  = floorz;
    mo->ceilingZ = ceilingz;
    mo->mom[MX] = mom[MX];
    mo->mom[MY] = mom[MY];
    mo->mom[MZ] = mom[MZ];
    mo->valid   = valid;
    mo->type    = type;
    mo->moveDir = DI_NODIR;

    /**
     * Continue reading the mobj data.
     */

    Reader_ReadInt32(svReader); // info

    mo->tics     = Reader_ReadInt32(svReader);
    mo->state    = INT2PTR(state_t, Reader_ReadInt32(svReader));
    mo->damage   = Reader_ReadInt32(svReader);
    mo->flags    = Reader_ReadInt32(svReader);
    mo->flags2   = Reader_ReadInt32(svReader);
    mo->special1 = Reader_ReadInt32(svReader);
    mo->special2 = Reader_ReadInt32(svReader);
    mo->health   = Reader_ReadInt32(svReader);

    // Fix a bunch of kludges in the original Heretic.
    switch(mo->type)
    {
    case MT_MACEFX1:
    case MT_MACEFX2:
    case MT_MACEFX3:
    case MT_HORNRODFX2:
    case MT_HEADFX3:
    case MT_WHIRLWIND:
    case MT_TELEGLITTER:
    case MT_TELEGLITTER2:
        mo->special3 = mo->health;
        mo->health = info->spawnHealth;
        break;

    default: break;
    }

    mo->moveDir      = Reader_ReadInt32(svReader);
    mo->moveCount    = Reader_ReadInt32(svReader);
    Reader_ReadInt32(svReader); // target
    mo->reactionTime = Reader_ReadInt32(svReader);
    mo->threshold    = Reader_ReadInt32(svReader);
    mo->player       = INT2PTR(player_t, Reader_ReadInt32(svReader));
    mo->lastLook     = Reader_ReadInt32(svReader);

    mo->spawnSpot.origin[VX] = (coord_t) Reader_ReadInt32(svReader);
    mo->spawnSpot.origin[VY] = (coord_t) Reader_ReadInt32(svReader);
    mo->spawnSpot.origin[VZ] = 0; // Initialize with "something".
    mo->spawnSpot.angle = (angle_t) (ANG45 * (Reader_ReadInt32(svReader) / 45));
    /*mo->spawnSpot.type = (int)*/ Reader_ReadInt32(svReader);

    {
    int spawnFlags = ((int) Reader_ReadInt32(svReader)) & ~MASK_UNKNOWN_MSF_FLAGS;
    // Spawn on the floor by default unless the mobjtype flags override.
    spawnFlags |= MSF_Z_FLOOR;
    mo->spawnSpot.flags = spawnFlags;
    }

    mo->info = info;
    SV_TranslateLegacyMobjFlags(mo, 0);

    mo->state = &STATES[PTR2INT(mo->state)];
    mo->target = NULL;
    if(mo->player)
    {
        mo->player = &players[PTR2INT(mo->player) - 1];
        mo->player->plr->mo = mo;
        mo->player->plr->mo->dPlayer = mo->player->plr;
    }
    P_MobjSetOrigin(mo);
    mo->floorZ   = P_GetDoublep(mo->bspLeaf, DMU_FLOOR_HEIGHT);
    mo->ceilingZ = P_GetDoublep(mo->bspLeaf, DMU_CEILING_HEIGHT);
}
Example #9
0
void T_PlatRaise(void *platThinkerPtr)
{
    plat_t *plat = (plat_t *)platThinkerPtr;
    result_e res;

    switch(plat->state)
    {
    case PS_UP:
        res = T_MovePlane(plat->sector, plat->speed, plat->high,
                          plat->crush, 0, 1);

        // Play a "while-moving" sound?
#if __JHERETIC__
        if(!(mapTime & 31))
            S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE);
#endif
#if __JDOOM__ || __JDOOM64__
        if(plat->type == PT_RAISEANDCHANGE ||
           plat->type == PT_RAISETONEARESTANDCHANGE)
        {
            if(!(mapTime & 7))
                S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE);
        }
#endif
        if(res == crushed && (!plat->crush))
        {
            plat->count = plat->wait;
            plat->state = PS_DOWN;
#if __JHEXEN__
            SN_StartSequenceInSec(plat->sector, SEQ_PLATFORM);
#else
# if __JDOOM64__
            if(plat->type != PT_DOWNWAITUPDOOR) // jd64 added test
# endif
                S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMSTART);
#endif
        }
        else
        {
            if(res == pastdest)
            {
                plat->count = plat->wait;
                plat->state = PS_WAIT;
#if __JHEXEN__
                SN_StopSequenceInSec(plat->sector);
#else
                S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMSTOP);
#endif
                switch(plat->type)
                {
                case PT_DOWNWAITUPSTAY:
#if __JHEXEN__
                case PT_DOWNBYVALUEWAITUPSTAY:
#else
# if !__JHERETIC__
                case PT_DOWNWAITUPSTAYBLAZE:
                case PT_RAISETONEARESTANDCHANGE:
# endif
# if __JDOOM64__
                case PT_DOWNWAITUPPLUS16STAYBLAZE: // jd64
                case PT_DOWNWAITUPDOOR: // jd64
# endif
                case PT_RAISEANDCHANGE:
#endif
                    stopPlat(plat);
                    break;

                default:
                    break;
                }
            }
        }
        break;

    case PS_DOWN:
        res =
            T_MovePlane(plat->sector, plat->speed, plat->low, false, 0, -1);

        if(res == pastdest)
        {
            plat->count = plat->wait;
            plat->state = PS_WAIT;

#if __JHEXEN__ || __JDOOM64__
            switch(plat->type)
            {
# if __JHEXEN__
            case PT_UPBYVALUEWAITDOWNSTAY:
# endif
            case PT_UPWAITDOWNSTAY:
                stopPlat(plat);
                break;

            default:
                break;
            }
#endif

#if __JHEXEN__
            SN_StopSequenceInSec(plat->sector);
#else
            S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMSTOP);
#endif
        }
        else
        {
            // Play a "while-moving" sound?
#if __JHERETIC__
            if(!(mapTime & 31))
                S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE);
#endif
        }
        break;

    case PS_WAIT:
        if(!--plat->count)
        {
            if(FEQUAL(P_GetDoublep(plat->sector, DMU_FLOOR_HEIGHT), plat->low))
                plat->state = PS_UP;
            else
                plat->state = PS_DOWN;
#if __JHEXEN__
            SN_StartSequenceInSec(plat->sector, SEQ_PLATFORM);
#else
            S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMSTART);
#endif
        }
        break;

    default:
        break;
    }
}
Example #10
0
static int doPlat(Line *line, int tag, plattype_e type, int amount)
#endif
{
#if !__JHEXEN__
    Sector *frontSector = (Sector *)P_GetPtrp(line, DMU_FRONT_SECTOR);
#endif

    iterlist_t *list = P_GetSectorIterListForTag(tag, false);
    if(!list) return 0;

    int rtn = 0;

    IterList_SetIteratorDirection(list, ITERLIST_FORWARD);
    IterList_RewindIterator(list);

    Sector *sec;
    while((sec = (Sector *)IterList_MoveIterator(list)))
    {
        xsector_t *xsec = P_ToXSector(sec);

        if(xsec->specialData)
            continue;

        // Find lowest & highest floors around sector
        rtn = 1;

        plat_t *plat = (plat_t *) Z_Calloc(sizeof(*plat), PU_MAP, 0);
        plat->thinker.function = T_PlatRaise;
        Thinker_Add(&plat->thinker);

        xsec->specialData = plat;

        plat->type   = type;
        plat->sector = sec;
        plat->crush  = false;
        plat->tag    = tag;
#if __JHEXEN__
        plat->speed  = (float) args[1] * (1.0 / 8);
#endif

        coord_t floorHeight = P_GetDoublep(sec, DMU_FLOOR_HEIGHT);

        switch(type)
        {
#if !__JHEXEN__
        case PT_RAISETONEARESTANDCHANGE:
            plat->speed = PLATSPEED * .5;

            P_SetPtrp(sec, DMU_FLOOR_MATERIAL,
                      P_GetPtrp(frontSector, DMU_FLOOR_MATERIAL));

            {
            coord_t nextFloor;
            if(P_FindSectorSurroundingNextHighestFloor(sec, floorHeight, &nextFloor))
                plat->high = nextFloor;
            else
                plat->high = floorHeight;
            }

            plat->wait = 0;
            plat->state = PS_UP;
            // No more damage if applicable.
            xsec->special = 0;
            S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE);
            break;

        case PT_RAISEANDCHANGE:
            plat->speed = PLATSPEED * .5;

            P_SetPtrp(sec, DMU_FLOOR_MATERIAL,
                      P_GetPtrp(frontSector, DMU_FLOOR_MATERIAL));

            plat->high = floorHeight + amount;
            plat->wait = 0;
            plat->state = PS_UP;
            S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE);
            break;
#endif
        case PT_DOWNWAITUPSTAY:
            P_FindSectorSurroundingLowestFloor(sec,
                P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low);
#if __JHEXEN__
            plat->low += 8;
#else
            plat->speed = PLATSPEED * 4;
#endif
            if(plat->low > floorHeight)
                plat->low = floorHeight;

            plat->high = floorHeight;
            plat->state = PS_DOWN;
#if __JHEXEN__
            plat->wait = (int) args[2];
#else
            plat->wait = PLATWAIT * TICSPERSEC;
#endif
#if !__JHEXEN__
            S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART);
#endif
            break;

#if __JDOOM64__ || __JHEXEN__
        case PT_UPWAITDOWNSTAY:
            P_FindSectorSurroundingHighestFloor(sec, -500, &plat->high);

            if(plat->high < floorHeight)
                plat->high = floorHeight;

            plat->low = floorHeight;
            plat->state = PS_UP;
# if __JHEXEN__
            plat->wait = (int) args[2];
# else
            plat->wait = PLATWAIT * TICSPERSEC;
# endif
# if __JDOOM64__
            plat->speed = PLATSPEED * 8;
            S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART);
# endif
            break;
#endif
#if __JDOOM64__
        case PT_DOWNWAITUPDOOR: // jd64
            plat->speed = PLATSPEED * 8;
            P_FindSectorSurroundingLowestFloor(sec,
                P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low);

            if(plat->low > floorHeight)
                plat->low = floorHeight;
            if(plat->low != floorHeight)
                plat->low += 6;

            plat->high = floorHeight;
            plat->wait = 50 * PLATWAIT;
            plat->state = PS_DOWN;
            break;
#endif
#if __JHEXEN__
       case PT_DOWNBYVALUEWAITUPSTAY:
            plat->low = floorHeight - (coord_t) args[3] * 8;
            if(plat->low > floorHeight)
                plat->low = floorHeight;
            plat->high = floorHeight;
            plat->wait = (int) args[2];
            plat->state = PS_DOWN;
            break;

        case PT_UPBYVALUEWAITDOWNSTAY:
            plat->high = floorHeight + (coord_t) args[3] * 8;
            if(plat->high < floorHeight)
                plat->high = floorHeight;
            plat->low = floorHeight;
            plat->wait = (int) args[2];
            plat->state = PS_UP;
            break;
#endif
#if __JDOOM__ || __JDOOM64__
        case PT_DOWNWAITUPSTAYBLAZE:
            plat->speed = PLATSPEED * 8;
            P_FindSectorSurroundingLowestFloor(sec,
                P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low);

            if(plat->low > floorHeight)
                plat->low = floorHeight;

            plat->high = floorHeight;
            plat->wait = PLATWAIT * TICSPERSEC;
            plat->state = PS_DOWN;
            S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART);
            break;
#endif
        case PT_PERPETUALRAISE:
            P_FindSectorSurroundingLowestFloor(sec,
                P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low);
#if __JHEXEN__
            plat->low += 8;
#else
            plat->speed = PLATSPEED;
#endif
            if(plat->low > floorHeight)
                plat->low = floorHeight;

            P_FindSectorSurroundingHighestFloor(sec, -500, &plat->high);

            if(plat->high < floorHeight)
                plat->high = floorHeight;

            plat->state = platstate_e(P_Random() & 1);
#if __JHEXEN__
            plat->wait = (int) args[2];
#else
            plat->wait = PLATWAIT * TICSPERSEC;
#endif
#if !__JHEXEN__
            S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART);
#endif
            break;

        default:
            break;
        }

#if __JHEXEN__
        SN_StartSequenceInSec(plat->sector, SEQ_PLATFORM);
#endif
    }

    return rtn;
}
Example #11
0
int EV_Teleport(Line* line, int side, mobj_t* mo, dd_bool spawnFog)
{
    mobj_t* dest;

    // Clients cannot teleport on their own.
    if(IS_CLIENT) return 0;

    if(mo->flags2 & MF2_NOTELEPORT) return 0;

    // Don't teleport if hit back of line, so you can get out of teleporter.
    if(side == 1) return 0;

    if((dest = getTeleportDestination(P_ToXLine(line)->tag)) != NULL)
    {
        // A suitable destination has been found.
        coord_t oldPos[3], aboveFloor;
        angle_t oldAngle;
        mobj_t* fog;
        uint an;

        memcpy(oldPos, mo->origin, sizeof(mo->origin));
        oldAngle = mo->angle;
        aboveFloor = mo->origin[VZ] - mo->floorZ;

        if(!P_TeleportMove(mo, dest->origin[VX], dest->origin[VY], false))
            return 0;

        mo->origin[VZ] = mo->floorZ;

        if(spawnFog)
        {
            // Spawn teleport fog at source and destination.
            if((fog = P_SpawnMobj(MT_TFOG, oldPos, oldAngle + ANG180, 0)))
                S_StartSound(SFX_TELEPT, fog);

            an = dest->angle >> ANGLETOFINESHIFT;
            if((fog = P_SpawnMobjXYZ(MT_TFOG, dest->origin[VX] + 20 * FIX2FLT(finecosine[an]),
                                              dest->origin[VY] + 20 * FIX2FLT(finesine[an]),
                                              mo->origin[VZ], dest->angle + ANG180, 0)))
            {
                // Emit sound, where?
                S_StartSound(SFX_TELEPT, fog);
            }
        }

        mo->angle = dest->angle;
        if(mo->flags2 & MF2_FLOORCLIP)
        {
            mo->floorClip = 0;

            if(FEQUAL(mo->origin[VZ], P_GetDoublep(Mobj_Sector(mo), DMU_FLOOR_HEIGHT)))
            {
                terraintype_t const *tt = P_MobjFloorTerrain(mo);
                if(tt->flags & TTF_FLOORCLIP)
                {
                    mo->floorClip = 10;
                }
            }
        }

        mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0;

        // $voodoodolls Must be the real player.
        if(mo->player && mo->player->plr->mo == mo)
        {
            mo->reactionTime = 18; // Don't move for a bit.
            if(mo->player->powers[PT_FLIGHT] && aboveFloor > 0)
            {
                mo->origin[VZ] = mo->floorZ + aboveFloor;
                if(mo->origin[VZ] + mo->height > mo->ceilingZ)
                {
                    mo->origin[VZ] = mo->ceilingZ - mo->height;
                }
            }
            else
            {
                //mo->dPlayer->clLookDir = 0; /* $unifiedangles */
                mo->dPlayer->lookDir = 0;
            }
            mo->player->viewHeight = (coord_t) cfg.common.plrViewHeight;
            mo->player->viewHeightDelta = 0;
            mo->player->viewZ = mo->origin[VZ] + mo->player->viewHeight;
            mo->player->viewOffset[VX] = mo->player->viewOffset[VY] = mo->player->viewOffset[VZ] = 0;
            mo->player->bob = 0;

            //mo->dPlayer->clAngle = mo->angle; /* $unifiedangles */
            mo->dPlayer->flags |= DDPF_FIXANGLES | DDPF_FIXORIGIN | DDPF_FIXMOM;
        }

        return 1;
    }
Example #12
0
int mobj_s::read(MapStateReader *msr)
{
#define FF_FULLBRIGHT 0x8000 ///< Used to be a flag in thing->frame.
#define FF_FRAMEMASK  0x7fff

    Reader1 *reader = msr->reader();

    int ver = Reader_ReadByte(reader);

#if !__JHEXEN__
    if(ver >= 2) // Version 2 has mobj archive numbers.
    {
        msr->addMobjToThingArchive(this, Reader_ReadInt16(reader));
    }
#endif

#if !__JHEXEN__
    target = 0;
    if(ver >= 2)
    {
        target   = INT2PTR(mobj_t, Reader_ReadInt16(reader));
    }
#endif

#if __JDOOM__ || __JDOOM64__
    tracer = 0;
    if(ver >= 5)
    {
        tracer   = INT2PTR(mobj_t, Reader_ReadInt16(reader));
    }
#endif

    onMobj = 0;
#if __JHEXEN__
    if(ver >= 8)
#else
    if(ver >= 5)
#endif
    {
        onMobj   = INT2PTR(mobj_t, Reader_ReadInt16(reader));
    }

    origin[VX]   = FIX2FLT(Reader_ReadInt32(reader));
    origin[VY]   = FIX2FLT(Reader_ReadInt32(reader));
    origin[VZ]   = FIX2FLT(Reader_ReadInt32(reader));
    angle        = Reader_ReadInt32(reader);
    sprite       = Reader_ReadInt32(reader);

    frame        = Reader_ReadInt32(reader); // might be ORed with FF_FULLBRIGHT
    if(frame & FF_FULLBRIGHT)
        frame &= FF_FRAMEMASK; // not used anymore.

#if __JHEXEN__
    if(ver < 6)
    {
        /*floorflat =*/ Reader_ReadInt32(reader);
    }
#else
    floorZ       = FIX2FLT(Reader_ReadInt32(reader));
    ceilingZ     = FIX2FLT(Reader_ReadInt32(reader));
#endif

    radius       = FIX2FLT(Reader_ReadInt32(reader));
    height       = FIX2FLT(Reader_ReadInt32(reader));
    mom[MX]      = FIX2FLT(Reader_ReadInt32(reader));
    mom[MY]      = FIX2FLT(Reader_ReadInt32(reader));
    mom[MZ]      = FIX2FLT(Reader_ReadInt32(reader));
    valid        = Reader_ReadInt32(reader);
    type         = Reader_ReadInt32(reader);

#if __JHEXEN__
    if(ver < 7)
    {
        /*info   = (mobjinfo_t *)*/ Reader_ReadInt32(reader);
    }
#endif
    info = &MOBJINFO[type];

    if(info->flags2 & MF2_FLOATBOB)
        mom[MZ] = 0;

    if(info->flags & MF_SOLID)
        ddFlags |= DDMF_SOLID;
    if(info->flags2 & MF2_DONTDRAW)
        ddFlags |= DDMF_DONTDRAW;

    tics         = Reader_ReadInt32(reader);
    state        = INT2PTR(state_t, Reader_ReadInt32(reader));
#if __JHEXEN__
    damage       = Reader_ReadInt32(reader);
#endif
    flags        = Reader_ReadInt32(reader);
#if __JHEXEN__
    flags2       = Reader_ReadInt32(reader);
    if(ver >= 5)
    {
        flags3   = Reader_ReadInt32(reader);
    }
    special1     = Reader_ReadInt32(reader);
    special2     = Reader_ReadInt32(reader);
#endif
    health       = Reader_ReadInt32(reader);

#if __JHERETIC__
    if(ver < 8)
    {
        // Fix a bunch of kludges in the original Heretic.
        switch(type)
        {
        case MT_MACEFX1:
        case MT_MACEFX2:
        case MT_MACEFX3:
        case MT_HORNRODFX2:
        case MT_HEADFX3:
        case MT_WHIRLWIND:
        case MT_TELEGLITTER:
        case MT_TELEGLITTER2:
            special3 = health;
            if(type == MT_HORNRODFX2 && special3 > 16)
                special3 = 16;
            health = MOBJINFO[type].spawnHealth;
            break;

        default:
            break;
        }
    }
#endif

    moveDir      = Reader_ReadInt32(reader);
    moveCount    = Reader_ReadInt32(reader);
#if __JHEXEN__
    target       = INT2PTR(mobj_t, Reader_ReadInt32(reader));
#endif
    reactionTime = Reader_ReadInt32(reader);
    threshold    = Reader_ReadInt32(reader);
    player       = INT2PTR(player_t, Reader_ReadInt32(reader));
    lastLook     = Reader_ReadInt32(reader);

#if __JHEXEN__
    floorClip    = FIX2FLT(Reader_ReadInt32(reader));
    msr->addMobjToThingArchive(this, Reader_ReadInt32(reader));
    tid          = Reader_ReadInt32(reader);
#else
    // For nightmare respawn.
    if(ver >= 6)
    {
        spawnSpot.origin[VX] = FIX2FLT(Reader_ReadInt32(reader));
        spawnSpot.origin[VY] = FIX2FLT(Reader_ReadInt32(reader));
        spawnSpot.origin[VZ] = FIX2FLT(Reader_ReadInt32(reader));
        spawnSpot.angle      = Reader_ReadInt32(reader);
        if(ver < 10)
        {
            /*spawnSpot.type =*/ Reader_ReadInt32(reader);
        }
        spawnSpot.flags      = Reader_ReadInt32(reader);
    }
    else
    {
        spawnSpot.origin[VX] = (float) Reader_ReadInt16(reader);
        spawnSpot.origin[VY] = (float) Reader_ReadInt16(reader);
        spawnSpot.origin[VZ] = 0; // Initialize with "something".
        spawnSpot.angle      = (angle_t) (ANG45 * (Reader_ReadInt16(reader) / 45));
        /*spawnSpot.type       = (int)*/ Reader_ReadInt16(reader);
        spawnSpot.flags      = (int) Reader_ReadInt16(reader);
    }

# if __JDOOM__ || __JDOOM64__
    if(ver >= 3)
# elif __JHERETIC__
    if(ver >= 5)
# endif
    {
        intFlags = Reader_ReadInt32(reader);
        dropOffZ = FIX2FLT(Reader_ReadInt32(reader));
        gear     = Reader_ReadInt32(reader);
    }

# if __JDOOM__ || __JDOOM64__
    if(ver >= 6)
    {
        damage = Reader_ReadInt32(reader);
        flags2 = Reader_ReadInt32(reader);
    }
    else // flags2 will be applied from the defs.
    {
        damage = DDMAXINT; // Use the value set in mo->info->damage
    }

# elif __JHERETIC__
    damage = Reader_ReadInt32(reader);
    flags2 = Reader_ReadInt32(reader);
# endif

    if(ver >= 7)
    {
        flags3 = Reader_ReadInt32(reader);
    } // Else flags3 will be applied from the defs.
#endif

#if __JHEXEN__
    special = Reader_ReadInt32(reader);
    Reader_Read(reader, args, 1 * 5);
#elif __JHERETIC__
    special1 = Reader_ReadInt32(reader);
    special2 = Reader_ReadInt32(reader);
    if(ver >= 8)
    {
        special3 = Reader_ReadInt32(reader);
    }
#endif

#if __JHEXEN__
    if(ver >= 2)
#else
    if(ver >= 4)
#endif
    {
        translucency = Reader_ReadByte(reader);
    }

#if __JHEXEN__
    if(ver >= 3)
#else
    if(ver >= 5)
#endif
    {
        visTarget = (short) (Reader_ReadByte(reader)) -1;
    }

#if __JHEXEN__
    if(ver >= 4)
    {
        tracer    = INT2PTR(mobj_t, Reader_ReadInt32(reader));
    }

    if(ver >= 4)
    {
        lastEnemy = INT2PTR(mobj_t, Reader_ReadInt32(reader));
    }
#else
    if(ver >= 5)
    {
        floorClip = FIX2FLT(Reader_ReadInt32(reader));
    }
#endif

#if __JHERETIC__
    if(ver >= 7)
    {
        generator = INT2PTR(mobj_t, Reader_ReadInt16(reader));
    }
    else
    {
        generator = 0;
    }
#endif

    /*
     * Restore! (unmangle)
     */
    info = &MOBJINFO[type];

    Mobj_SetState(this, PTR2INT(state));
#if __JHEXEN__
    if(flags2 & MF2_DORMANT)
    {
        tics = -1;
    }
#endif

    if(player)
    {
        // The player number translation table is used to find out the
        // *current* (actual) player number of the referenced player.
        player = msr->player(PTR2INT(player));
#if __JHEXEN__
        if(!player)
        {
            // This saved player does not exist in the current game!
            // Destroy this mobj.
            Mobj_Destroy(this);
            return false;
        }
#endif
        dPlayer = player->plr;

        dPlayer->mo      = this;
        //dPlayer->clAngle = angle; /* $unifiedangles */
        dPlayer->lookDir = 0; /* $unifiedangles */
    }

    visAngle = angle >> 16;

#if !__JHEXEN__
    if(dPlayer && !dPlayer->inGame)
    {
        dPlayer->mo = 0;
        Mobj_Destroy(this);
        return false;
    }
#endif

#if !__JDOOM64__
    // Do we need to update this mobj's flag values?
    if(ver < MOBJ_SAVEVERSION)
    {
        SV_TranslateLegacyMobjFlags(this, ver);
    }
#endif

    P_MobjLink(this);
    floorZ   = P_GetDoublep(Mobj_Sector(this), DMU_FLOOR_HEIGHT);
    ceilingZ = P_GetDoublep(Mobj_Sector(this), DMU_CEILING_HEIGHT);

    return false;

#undef FF_FRAMEMASK
#undef FF_FULLBRIGHT
}
Example #13
0
void Mobj_XYMoveStopping(mobj_t *mo)
{
    DENG_ASSERT(mo != 0);

    player_t *player = mo->player;

    if(player && (P_GetPlayerCheats(player) & CF_NOMOMENTUM))
    {
        // Debug option for no sliding at all.
        mo->mom[MX] = mo->mom[MY] = 0;
        return;
    }

    if(mo->flags & (MF_MISSILE | MF_SKULLFLY))
    {
        // No friction for missiles.
        return;
    }

    if(mo->origin[VZ] > mo->floorZ && !mo->onMobj && !(mo->flags2 & MF2_FLY))
    {
        // No friction when falling.
        return;
    }

#ifndef __JHEXEN__
    if(cfg.slidingCorpses)
    {
        // $dropoff_fix: Add objects falling off ledges. Does not apply to players!
        if(((mo->flags & MF_CORPSE) || (mo->intFlags & MIF_FALLING)) && !mo->player)
        {
            // Do not stop sliding if halfway off a step with some momentum.
            if(!INRANGE_OF(mo->mom[MX], 0, DROPOFFMOMENTUM_THRESHOLD) ||
               !INRANGE_OF(mo->mom[MY], 0, DROPOFFMOMENTUM_THRESHOLD))
            {
                if(!FEQUAL(mo->floorZ, P_GetDoublep(Mobj_Sector(mo), DMU_FLOOR_HEIGHT)))
                    return;
            }
        }
    }
#endif

    bool isVoodooDoll = Mobj_IsVoodooDoll(mo);
    bool belowWalkStop = (INRANGE_OF(mo->mom[MX], 0, WALKSTOP_THRESHOLD) &&
                          INRANGE_OF(mo->mom[MY], 0, WALKSTOP_THRESHOLD));

    bool belowStandSpeed = false;
    bool isMovingPlayer  = false;
    if(player)
    {
        belowStandSpeed = (INRANGE_OF(mo->mom[MX], 0, STANDSPEED) &&
                           INRANGE_OF(mo->mom[MY], 0, STANDSPEED));
        isMovingPlayer = (!FEQUAL(player->plr->forwardMove, 0) ||
                        !FEQUAL(player->plr->sideMove, 0));
    }

    // Stop player walking animation (only real players).
    if(!isVoodooDoll && player && belowStandSpeed && !isMovingPlayer &&
        !IS_NETWORK_SERVER) // Netgame servers use logic elsewhere for player animation.
    {
        // If in a walking frame, stop moving.
        if(P_PlayerInWalkState(player))
        {
            P_MobjChangeState(player->plr->mo, statenum_t(PCLASS_INFO(player->class_)->normalState));
        }
    }

    // Apply friction.
    if(belowWalkStop && !isMovingPlayer)
    {
        // $voodoodolls: Do not zero mom for voodoo dolls!
        if(!isVoodooDoll)
        {
            // Momentum is below the walkstop threshold; stop it completely.
            mo->mom[MX] = mo->mom[MY] = 0;

            // $voodoodolls: Stop view bobbing if this isn't a voodoo doll.
            if(player) player->bob = 0;
        }
    }
    else
    {
        coord_t friction = Mobj_Friction(mo);
        mo->mom[MX] *= friction;
        mo->mom[MY] *= friction;
    }
}