예제 #1
0
mobj_t *P_LaunchMissile(mobj_t *missile, angle_t angle, coord_t const targetPos[],
    coord_t const sourcePos[], coord_t extraMomZ)
{
    DENG2_ASSERT(targetPos);
    if(missile)
    {
        DENG2_ASSERT(missile->info);

        // Play the launch sound.
        if(missile->info->seeSound)
        {
            S_StartSound(missile->info->seeSound, missile);
        }

        if(!sourcePos)
        {
            sourcePos = missile->origin;
        }

        // Determine speed.
        /// @todo Should optionally calculate this in true 3D.
        coord_t dist;
        uint an = angle >> ANGLETOFINESHIFT;
        missile->mom[0] = missile->info->speed * FIX2FLT(finecosine[an]);
        missile->mom[1] = missile->info->speed * FIX2FLT(finesine  [an]);

        dist = M_ApproxDistance(targetPos[0] - sourcePos[0], targetPos[1] - sourcePos[1]);
        dist /= missile->info->speed;
        if(dist < 1) dist = 1;

        missile->mom[2] = (targetPos[2] - sourcePos[2] + extraMomZ) / dist;
    }
    return Mobj_ExplodeIfObstructed(missile);
}
예제 #2
0
void C_DECL A_Quake(mobj_t* actor)
{
    angle_t angle;
    player_t* player;
    mobj_t* victim;
    int richters = actor->args[0];
    int playnum;
    coord_t dist;

    if(actor->args[1]-- > 0)
    {
        for(playnum = 0; playnum < MAXPLAYERS; ++playnum)
        {
            player = &players[playnum];
            if(!players[playnum].plr->inGame)
                continue;

            victim = player->plr->mo;
            dist =  M_ApproxDistance(actor->origin[VX] - victim->origin[VX],
                                     actor->origin[VY] - victim->origin[VY]);

            dist = FIX2FLT(FLT2FIX(dist) >> (FRACBITS + 6));

            // Tested in tile units (64 pixels).
            if(dist < FIX2FLT(actor->args[3])) // In tremor radius.
            {
                localQuakeHappening[playnum] = richters;
                players[playnum].update |= PSF_LOCAL_QUAKE;
            }

            // Check if in damage radius.
            if(dist < FIX2FLT(actor->args[2]) &&
                    victim->origin[VZ] <= victim->floorZ)
            {
                if(P_Random() < 50)
                {
                    P_DamageMobj(victim, NULL, NULL, HITDICE(1), false);
                }

                // Thrust player around.
                angle = victim->angle + ANGLE_1 * P_Random();
                P_ThrustMobj(victim, angle, FIX2FLT(richters << (FRACBITS - 1)));
            }
        }
    }
    else
    {
        for(playnum = 0; playnum < MAXPLAYERS; playnum++)
예제 #3
0
dd_bool Mobj_LookForPlayers(mobj_t *mo, dd_bool allAround)
{
    int const playerCount = P_CountPlayersInGame();

    // Nobody to target?
    if(!playerCount) return false;

    int const from = mo->lastLook % MAXPLAYERS;
    int const to   = (from + MAXPLAYERS - 1) % MAXPLAYERS;

    int cand         = from;
    int tries        = 0;
    bool foundTarget = false;
    for(; cand != to; cand = (cand < (MAXPLAYERS - 1)? cand + 1 : 0))
    {
        player_t *player = players + cand;

        // Is player in the game?
        if(!player->plr->inGame) continue;

        mobj_t *plrmo = player->plr->mo;
        if(!plrmo) continue;

        // Do not target camera players.
        if(P_MobjIsCamera(plrmo)) continue;

        // Only look ahead a fixed number of times.
        if(tries++ == 2) break;

        // Do not target dead players.
        if(player->health <= 0) continue;

        // Within sight?
        if(!P_CheckSight(mo, plrmo)) continue;

        if(!allAround)
        {
            angle_t an = M_PointToAngle2(mo->origin, plrmo->origin);
            an -= mo->angle;

            if(an > ANG90 && an < ANG270)
            {
                // If real close, react anyway.
                coord_t dist = M_ApproxDistance(plrmo->origin[VX] - mo->origin[VX],
                                                plrmo->origin[VY] - mo->origin[VY]);
                // Behind us?
                if(dist > MELEERANGE) continue;
            }
        }

#if __JHERETIC__ || __JHEXEN__
        // If player is invisible we may not detect if too far or randomly.
        if(plrmo->flags & MF_SHADOW)
        {
            if((M_ApproxDistance(plrmo->origin[VX] - mo->origin[VX],
                                 plrmo->origin[VY] - mo->origin[VY]) > 2 * MELEERANGE) &&
               M_ApproxDistance(plrmo->mom[MX], plrmo->mom[MY]) < 5)
            {
                // Too far; can't detect.
                continue;
            }

            // Randomly overlook the player regardless.
            if(P_Random() < 225) continue;
        }
#endif

#if __JHEXEN__
        // Minotaurs do not target their master.
        if(mo->type == MT_MINOTAUR && mo->tracer &&
           mo->tracer->player == player) continue;
#endif

        // Found our quarry.
        mo->target = plrmo;
        foundTarget = true;
    }

    // Start looking from here next time.
    mo->lastLook = cand;
    return foundTarget;
}
예제 #4
0
/**
 * Set appropriate parameters for a camera.
 */
void P_PlayerThinkCamera(player_t* player)
{
    mobj_t* mo = player->plr->mo;

    if(!mo) return;

    // If this player is not a camera, get out of here.
    if(!(player->plr->flags & DDPF_CAMERA))
    {
        if(player->playerState == PST_LIVE)
        {
            mo->flags |= (MF_SOLID | MF_SHOOTABLE | MF_PICKUP);
        }
        return;
    }

    mo->flags &= ~(MF_SOLID | MF_SHOOTABLE | MF_PICKUP);

    // How about viewlock?
    if(player->viewLock)
    {
        angle_t angle;
        int full;
        coord_t dist;
        mobj_t* target = players->viewLock;

        if(!target->player || !target->player->plr->inGame)
        {
            player->viewLock = NULL;
            return;
        }

        full = player->lockFull;

        angle = M_PointToAngle2(mo->origin, target->origin);
        //player->plr->flags |= DDPF_FIXANGLES;
        /* $unifiedangles */
        mo->angle = angle;
        //player->plr->clAngle = angle;
        player->plr->flags |= DDPF_INTERYAW;

        if(full)
        {
            dist = M_ApproxDistance(mo->origin[VX] - target->origin[VX],
                                    mo->origin[VY] - target->origin[VY]);
            angle = M_PointXYToAngle2(0, 0,
                                      target->origin[VZ] + (target->height / 2) - mo->origin[VZ],
                                      dist);

            player->plr->lookDir = -(angle / (float) ANGLE_MAX * 360.0f - 90);
            if(player->plr->lookDir > 180)
                player->plr->lookDir -= 360;

            player->plr->lookDir *= 110.0f / 85.0f;

            if(player->plr->lookDir > 110)
                player->plr->lookDir = 110;
            if(player->plr->lookDir < -110)
                player->plr->lookDir = -110;

            player->plr->flags |= DDPF_INTERPITCH;
        }
    }
}