Example #1
0
void C_DECL A_CorpseExplode(mobj_t* actor)
{
    int i, n;
    mobj_t* mo;

    for(i = (P_Random() & 3) + 3; i; i--)
    {
        if((mo = P_SpawnMobj(MT_CORPSEBIT, actor->origin, P_Random() << 24, 0)))
        {
            P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN) + (P_Random() % 3));

            mo->mom[MZ] = FIX2FLT((P_Random() & 7) + 5) * .75f;
            mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10);
            mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10);
        }
    }

    // Spawn a skull.
    if((mo = P_SpawnMobj(MT_CORPSEBIT, actor->origin, P_Random() << 24, 0)))
    {
        P_MobjChangeState(mo, S_CORPSEBIT_4);

        n = (P_Random() & 7) + 5;
        mo->mom[MZ] = FIX2FLT(n) * .75f;
        mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10);
        mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10);
        S_StartSound(SFX_FIRED_DEATH, mo);
    }
    P_MobjRemove(actor, false);
}
Example #2
0
void C_DECL A_LeafCheck(mobj_t *actor)
{
    int                 n;

    actor->special1++;
    if(actor->special1 >= 20)
    {
        P_MobjChangeState(actor, S_NULL);
        return;
    }

    if(P_Random() > 64)
    {
        if(FEQUAL(actor->mom[MX], 0) && FEQUAL(actor->mom[MY], 0))
        {
            P_ThrustMobj(actor, actor->target->angle,
                         FIX2FLT(P_Random() << 9) + 1);
        }
        return;
    }

    P_MobjChangeState(actor, S_LEAF1_8);
    n = P_Random();
    actor->mom[MZ] = FIX2FLT(n << 9) + 1;
    P_ThrustMobj(actor, actor->target->angle, FIX2FLT(P_Random() << 9) + 2);
    actor->flags |= MF_MISSILE;
}
Example #3
0
void C_DECL A_PotteryCheck(mobj_t* actor)
{
    mobj_t* pmo;

    if(!IS_NETGAME)
    {
        pmo = players[CONSOLEPLAYER].plr->mo;
        if(P_CheckSight(actor, pmo) &&
                (abs((int32_t)(M_PointToAngle2(pmo->origin, actor->origin) - pmo->angle)) <= ANGLE_45))
        {
            // Previous state (pottery bit waiting state).
            P_MobjChangeState(actor, actor->state - &STATES[0] - 1);
        }

        return;
    }
    else
    {
        int i;
        for(i = 0; i < MAXPLAYERS; ++i)
        {
            if(!players[i].plr->inGame) continue;

            pmo = players[i].plr->mo;
            if(P_CheckSight(actor, pmo) &&
                    (abs((int32_t)(M_PointToAngle2(pmo->origin, actor->origin) - pmo->angle)) <= ANGLE_45))
            {
                // Previous state (pottery bit waiting state).
                P_MobjChangeState(actor, actor->state - &STATES[0] - 1);
                return;
            }
        }
    }
}
Example #4
0
/**
 * NOTE: See p_enemy for variable descriptions.
 */
void C_DECL A_Summon(mobj_t* actor)
{
    mobj_t*             mo;

    if((mo = P_SpawnMobj(MT_MINOTAUR, actor->origin, actor->angle, 0)))
    {
        mobj_t*             master;

        if(P_TestMobjLocation(mo) == false || !actor->tracer)
        {   // Didn't fit - change back to item.
            P_MobjChangeState(mo, S_NULL);

            if((mo = P_SpawnMobj(MT_SUMMONMAULATOR, actor->origin, actor->angle, 0)))
                mo->flags2 |= MF2_DROPPED;

            return;
        }

        memcpy((void *) mo->args, &mapTime, sizeof(mapTime));
        master = actor->tracer;
        if(master->flags & MF_CORPSE)
        {   // Master dead.
            mo->tracer = NULL; // No master.
        }
        else
        {
            mo->tracer = actor->tracer; // Pointer to master (mobj_t *)
            P_GivePower(master->player, PT_MINOTAUR);
        }

        // Make smoke puff.
        P_SpawnMobj(MT_MNTRSMOKE, actor->origin, P_Random() << 24, 0);
        S_StartSound(SFX_MAULATOR_ACTIVE, actor);
    }
}
Example #5
0
void C_DECL A_PotteryExplode(mobj_t* actor)
{
    int i, maxBits = (P_Random() & 3) + 3;
    mobj_t* potteryBit;

    for(i = 0; i < maxBits; ++i)
    {
        if((potteryBit = P_SpawnMobj(MT_POTTERYBIT1, actor->origin, P_Random() << 24, 0)))
        {
            P_MobjChangeState(potteryBit, P_GetState(potteryBit->type, SN_SPAWN) + (P_Random() % 5));

            potteryBit->mom[MZ] = FIX2FLT(((P_Random() & 7) + 5) * (3 * FRACUNIT / 4));
            potteryBit->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10);
            potteryBit->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10);
        }
    }

    S_StartSound(SFX_POTTERY_EXPLODE, potteryBit);

    if(actor->args[0])
    {
        // Spawn an item.
        if(!G_Ruleset_NoMonsters() ||
                !(MOBJINFO[TranslateThingType[actor->args[0]]].
                  flags & MF_COUNTKILL))
        {
            // Only spawn monsters if not -nomonsters.
            P_SpawnMobj(TranslateThingType[actor->args[0]], actor->origin,
                        actor->angle, 0);
        }
    }

    P_MobjRemove(actor, false);
}
Example #6
0
void C_DECL A_CheckThrowBomb(mobj_t* actor)
{
    if(fabs(actor->mom[MX]) < 1.5f && fabs(actor->mom[MY]) < 1.5f &&
            actor->mom[MZ] < 2 && actor->state == &STATES[S_THROWINGBOMB6])
    {
        P_MobjChangeState(actor, S_THROWINGBOMB7);
        actor->origin[VZ] = actor->floorZ;
        actor->mom[MZ] = 0;
        actor->flags2 &= ~MF2_FLOORBOUNCE;
        actor->flags &= ~MF_MISSILE;
        actor->flags |= MF_VIEWALIGN;
    }

    if(!--actor->health)
    {
        P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH));
    }
}
Example #7
0
void C_DECL A_PoisonBagCheck(mobj_t *actor)
{
    if(!--actor->special1)
    {
        P_MobjChangeState(actor, S_POISONCLOUD_X1);
    }
    else
    {
        return;
    }
}
Example #8
0
/**
 * The player can fire the weapon or change to another weapon at this time.
 * Follows after getting weapon up, or after previous attack/fire sequence.
 */
void C_DECL A_WeaponReady(player_t* player, pspdef_t* psp)
{
    weaponmodeinfo_t*   wminfo;

    // Enable the pspr Y offset (might be disabled in A_Lower).
    DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 1000);

    // Get out of attack state.
    if(player->plr->mo->state == &STATES[PCLASS_INFO(player->class_)->attackState] ||
       player->plr->mo->state == &STATES[PCLASS_INFO(player->class_)->attackEndState])
    {
        P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class_)->normalState);
    }

    if(player->readyWeapon != WT_NOCHANGE)
    {
        wminfo = WEAPON_INFO(player->readyWeapon, player->class_, 0);

        // A weaponready sound?
        if(psp->state == &STATES[wminfo->states[WSN_READY]] && wminfo->readySound)
            S_StartSound(wminfo->readySound, player->plr->mo);

        // Check for change. If player is dead, put the weapon away.
        if(player->pendingWeapon != WT_NOCHANGE || !player->health)
        {   //  (pending weapon should allready be validated)
            P_SetPsprite(player, ps_weapon, wminfo->states[WSN_DOWN]);
            return;
        }
    }

    // Check for autofire.
    if(player->brain.attack)
    {
        wminfo = WEAPON_INFO(player->readyWeapon, player->class_, 0);

        if(!player->attackDown || wminfo->autoFire)
        {
            player->attackDown = true;
            P_FireWeapon(player);
            return;
        }
    }
    else
        player->attackDown = false;

    // Bob the weapon based on movement speed.
    R_GetWeaponBob(player - players, &psp->pos[0], &psp->pos[1]);

    // Psprite state.
    player->plr->pSprites[0].state = DDPSP_BOBBING;
}
Example #9
0
void P_FireWeapon(player_t *player)
{
    statenum_t          newstate;

    if(!P_CheckAmmo(player))
        return;

    // Psprite state.
    player->plr->pSprites[0].state = DDPSP_FIRE;

    P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class_)->attackState);
    newstate = weaponInfo[player->readyWeapon][player->class_].mode[0].states[WSN_ATTACK];
    P_SetPsprite(player, ps_weapon, newstate);
    P_NoiseAlert(player->plr->mo, player->plr->mo);
}
Example #10
0
void C_DECL A_BridgeOrbit(mobj_t* actor)
{
    if(!actor) return;

    if(actor->target->special1)
    {
        P_MobjChangeState(actor, S_NULL);
    }
    actor->args[0] += 3;

    P_MobjUnlink(actor);

    actor->origin[VX] = actor->target->origin[VX];
    actor->origin[VY] = actor->target->origin[VY];

    actor->origin[VX] += orbitTableX[actor->args[0]];
    actor->origin[VY] += orbitTableY[actor->args[0]];

    P_MobjLink(actor);
}
Example #11
0
static dd_bool DeactivateThing(mobj_t *mobj)
{
    if(mobj->flags & MF_COUNTKILL)
    {                           // Monster
        if(!(mobj->flags2 & MF2_DORMANT))
        {
            mobj->flags2 |= MF2_DORMANT;
            mobj->tics = -1;
            return true;
        }
        return false;
    }

    switch(mobj->type)
    {
    case MT_ZTWINEDTORCH:
    case MT_ZTWINEDTORCH_UNLIT:
        P_MobjChangeState(mobj, S_ZTWINEDTORCH_UNLIT);
        break;

    case MT_ZWALLTORCH:
    case MT_ZWALLTORCH_UNLIT:
        P_MobjChangeState(mobj, S_ZWALLTORCH_U);
        break;

    case MT_THRUSTFLOOR_UP:
    case MT_THRUSTFLOOR_DOWN:
        if(mobj->args[0] == 1)
        {
            S_StartSound(SFX_THRUSTSPIKE_RAISE, mobj);
            if(mobj->args[1])
                P_MobjChangeState(mobj, S_BTHRUSTLOWER);
            else
                P_MobjChangeState(mobj, S_THRUSTLOWER);
        }
        break;

    case MT_ZFIREBULL:
    case MT_ZFIREBULL_UNLIT:
        P_MobjChangeState(mobj, S_ZFIREBULL_DEATH);
        break;

    case MT_ZCAULDRON:
    case MT_ZCAULDRON_UNLIT:
        P_MobjChangeState(mobj, S_ZCAULDRON_U);
        break;

    case MT_FLAME_SMALL:
        P_MobjChangeState(mobj, S_FLAME_SDORM1);
        break;

    case MT_FLAME_LARGE:
        P_MobjChangeState(mobj, S_FLAME_LDORM1);
        break;

    case MT_BAT_SPAWNER:
        P_MobjChangeState(mobj, S_SPAWNBATS_OFF);
        break;

    default:
        return false;
        break;
    }
    return true;
}
Example #12
0
static dd_bool ActivateThing(mobj_t *mobj)
{
    if(mobj->flags & MF_COUNTKILL)
    {                           // Monster
        if(mobj->flags2 & MF2_DORMANT)
        {
            mobj->flags2 &= ~MF2_DORMANT;
            mobj->tics = 1;
            return true;
        }
        return false;
    }

    switch(mobj->type)
    {
    case MT_ZTWINEDTORCH:
    case MT_ZTWINEDTORCH_UNLIT:
        P_MobjChangeState(mobj, S_ZTWINEDTORCH_1);
        S_StartSound(SFX_IGNITE, mobj);
        break;

    case MT_ZWALLTORCH:
    case MT_ZWALLTORCH_UNLIT:
        P_MobjChangeState(mobj, S_ZWALLTORCH1);
        S_StartSound(SFX_IGNITE, mobj);
        break;

    case MT_ZGEMPEDESTAL:
        P_MobjChangeState(mobj, S_ZGEMPEDESTAL2);
        break;

    case MT_ZWINGEDSTATUENOSKULL:
        P_MobjChangeState(mobj, S_ZWINGEDSTATUENOSKULL2);
        break;

    case MT_THRUSTFLOOR_UP:
    case MT_THRUSTFLOOR_DOWN:
        if(mobj->args[0] == 0)
        {
            S_StartSound(SFX_THRUSTSPIKE_LOWER, mobj);
            mobj->flags2 &= ~MF2_DONTDRAW;
            if(mobj->args[1])
                P_MobjChangeState(mobj, S_BTHRUSTRAISE1);
            else
                P_MobjChangeState(mobj, S_THRUSTRAISE1);
        }
        break;

    case MT_ZFIREBULL:
    case MT_ZFIREBULL_UNLIT:
        P_MobjChangeState(mobj, S_ZFIREBULL_BIRTH);
        S_StartSound(SFX_IGNITE, mobj);
        break;

    case MT_ZBELL:
        if(mobj->health > 0)
        {
            P_DamageMobj(mobj, NULL, NULL, 10, false); // 'ring' the bell
        }
        break;

    case MT_ZCAULDRON:
    case MT_ZCAULDRON_UNLIT:
        P_MobjChangeState(mobj, S_ZCAULDRON1);
        S_StartSound(SFX_IGNITE, mobj);
        break;

    case MT_FLAME_SMALL:
        S_StartSound(SFX_IGNITE, mobj);
        P_MobjChangeState(mobj, S_FLAME_SMALL1);
        break;

    case MT_FLAME_LARGE:
        S_StartSound(SFX_IGNITE, mobj);
        P_MobjChangeState(mobj, S_FLAME_LARGE1);
        break;

    case MT_BAT_SPAWNER:
        P_MobjChangeState(mobj, S_SPAWNBATS1);
        break;

    default:
        return false;
        break;
    }
    return true;
}
Example #13
0
void C_DECL A_GunFlash(player_t *player, pspdef_t *psp)
{
    P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class_)->attackEndState);
    P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class_].mode[0].states[WSN_FLASH]);
}
Example #14
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;
    }
}
Example #15
0
void P_KillMobj(mobj_t *source, mobj_t *target, dd_bool stomping)
{
    mobjtype_t          item;
    mobj_t*             mo;
    unsigned int        an;
    angle_t             angle;

    if(!target)
        return; // Nothing to kill...

    target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY);

    if(target->type != MT_SKULL)
        target->flags &= ~MF_NOGRAVITY;

    target->flags |= MF_CORPSE | MF_DROPOFF;
    target->flags2 &= ~MF2_PASSMOBJ;
    target->corpseTics = 0;
    target->height /= 2*2;

    if(source && source->player)
    {
        // Count for intermission.
        if(target->flags & MF_COUNTKILL)
        {
            source->player->killCount++;
            source->player->update |= PSF_COUNTERS;
        }

        if(target->player)
        {
            source->player->frags[target->player - players]++;
            NetSv_FragsForAll(source->player);
            NetSv_KillMessage(source->player, target->player, stomping);
        }
    }
    else if(!IS_NETGAME && (target->flags & MF_COUNTKILL))
    {
        // Count all monster deaths (even those caused by other monsters).
        players[0].killCount++;
    }

    if(target->player)
    {
        // Count environment kills against the player.
        if(!source)
        {
            target->player->frags[target->player - players]++;
            NetSv_FragsForAll(target->player);
            NetSv_KillMessage(target->player, target->player, stomping);
        }

        target->flags &= ~MF_SOLID;
        target->flags2 &= ~MF2_FLY;
        target->player->powers[PT_FLIGHT] = 0;
        target->player->playerState = PST_DEAD;
        target->player->rebornWait = PLAYER_REBORN_TICS;
        target->player->update |= PSF_STATE;
        target->player->plr->flags |= DDPF_DEAD;
        P_DropWeapon(target->player);

        // Don't die with the automap open.
        ST_AutomapOpen(target->player - players, false, false);
#if __JHERETIC__ || __JHEXEN__
        Hu_InventoryOpen(target->player - players, false);
#endif
    }

    if(target->health < -target->info->spawnHealth &&
       P_GetState(target->type, SN_XDEATH))
    {   // Extreme death.
        P_MobjChangeState(target, P_GetState(target->type, SN_XDEATH));
    }
    else
    {   // Normal death.
        P_MobjChangeState(target, P_GetState(target->type, SN_DEATH));
    }

    target->tics -= P_Random() & 3;

    if(target->tics < 1)
        target->tics = 1;

    // Enemies in Chex Quest don't drop stuff.
    if(gameMode == doom_chex)
        return;

    // Drop stuff.
    // This determines the kind of object spawned during the death frame
    // of a thing.
    switch(target->type)
    {
    case MT_WOLFSS:
    case MT_POSSESSED:
        item = MT_CLIP;
        break;

    case MT_SHOTGUY:
        item = MT_SHOTGUN;
        break;

    case MT_CHAINGUY:
        item = MT_CHAINGUN;
        break;

    default:
        return;
    }

    // Don't drop at the exact same place, causes Z flickering with
    // 3D sprites.
    angle = P_Random() << 24;
    an = angle >> ANGLETOFINESHIFT;
    if((mo = P_SpawnMobjXYZ(item, target->origin[VX] + 3 * FIX2FLT(finecosine[an]),
                            target->origin[VY] + 3 * FIX2FLT(finesine[an]),
                            0, angle, MSF_Z_FLOOR)))
        mo->flags |= MF_DROPPED; // Special versions of items.
}
Example #16
0
void C_DECL A_PotteryChooseBit(mobj_t* actor)
{
    P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH) + (P_Random() % 5) + 1);
    actor->tics = 256 + (P_Random() << 1);
}
Example #17
0
void C_DECL A_BridgeRemove(mobj_t *actor)
{
    actor->special1 = true; // Removing the bridge.
    actor->flags &= ~MF_SOLID;
    P_MobjChangeState(actor, S_FREE_BRIDGE1);
}