Beispiel #1
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;
            }
        }
    }
}
Beispiel #2
0
void C_DECL A_Punch(player_t *player, pspdef_t *psp)
{
    angle_t angle;
    int damage;
    float slope;

    P_ShotAmmo(player);
    player->update |= PSF_AMMO;

    if(IS_CLIENT) return;

    damage = (P_Random() % 10 + 1) * 2;
    if(player->powers[PT_STRENGTH])
        damage *= 10;

    angle = player->plr->mo->angle;
    angle += (P_Random() - P_Random()) << 18;
    slope = P_AimLineAttack(player->plr->mo, angle, PLRMELEERANGE);
    P_LineAttack(player->plr->mo, angle, PLRMELEERANGE, slope, damage, MT_PUFF);

    // Turn to face target.
    if(lineTarget)
    {
        S_StartSound(SFX_PUNCH, player->plr->mo);

        player->plr->mo->angle = M_PointToAngle2(player->plr->mo->origin, lineTarget->origin);
        player->plr->flags |= DDPF_FIXANGLES;
    }
}
Beispiel #3
0
void C_DECL A_Saw(player_t *player, pspdef_t *psp)
{
    angle_t angle;
    int damage;
    float slope;

    DENG_UNUSED(psp);

    P_ShotAmmo(player);
    player->update |= PSF_AMMO;

    if(IS_CLIENT) return;

    damage = (float) (P_Random() % 10 + 1) * 2;
    angle = player->plr->mo->angle;
    angle += (P_Random() - P_Random()) << 18;

    // Use meleerange + 1 so the puff doesn't skip the flash.
    slope = P_AimLineAttack(player->plr->mo, angle, PLRMELEERANGE + 1);
    P_LineAttack(player->plr->mo, angle, PLRMELEERANGE + 1, slope, damage, MT_PUFF);

    if(!lineTarget)
    {
        S_StartSound(SFX_SAWFUL, player->plr->mo);
        return;
    }

    S_StartSound(SFX_SAWHIT, player->plr->mo);

    // Turn to face target.
    angle = M_PointToAngle2(player->plr->mo->origin, lineTarget->origin);
    if(angle - player->plr->mo->angle > ANG180)
    {
        if(angle - player->plr->mo->angle < -ANG90 / 32) // jd64 was "/ 20"
            player->plr->mo->angle = angle + ANG90 / 32; // jd64 was "/ 21"
        else
            player->plr->mo->angle -= ANG90 / 20;
    }
    else
    {
        if(angle - player->plr->mo->angle > ANG90 / 32) // jd64 was "/ 20"
            player->plr->mo->angle = angle - ANG90 / 32; // jd64 was "/ 21"
        else
            player->plr->mo->angle += ANG90 / 20;
    }
    player->plr->mo->flags |= MF_JUSTATTACKED;
}
Beispiel #4
0
/**
 * Damages both enemies and players.
 *
 * @param inflictor     Mobj that caused the damage creature or missile,
 *                      can be NULL (slime, etc)
 * @param source        Mobj to target after taking damage. Can be @c NULL
 *                      for barrel explosions and other environmental stuff.
 *                      Source and inflictor are the same for melee attacks.
 * @param skipNetworkCheck  Allow the damage to be done regardless of netgame status.
 *
 * @return              Actual amount of damage done.
 */
int P_DamageMobj2(mobj_t *target, mobj_t *inflictor, mobj_t *source,
                  int damageP, dd_bool stomping, dd_bool skipNetworkCheck)
{
    angle_t angle;
    int saved, originalHealth;
    player_t *player;
    int /*temp,*/ damage;

    if(!target)
        return 0; // Wha?

    originalHealth = target->health;

    // The actual damage (== damageP * netMobDamageModifier for any
    // non-player mobj).
    damage = damageP;

    if(!skipNetworkCheck)
    {
        if(IS_NETGAME && !stomping && D_NetDamageMobj(target, inflictor, source, damage))
        {   // We're done here.
            return 0;
        }
        // Clients can't harm anybody.
        if(IS_CLIENT)
            return 0;
    }

    if(!(target->flags & MF_SHOOTABLE))
        return 0; // Shouldn't happen...

    if(target->health <= 0)
        return 0;

    if(target->player)
    {   // Player specific.
        // Check if player-player damage is disabled.
        if(source && source->player && source->player != target->player)
        {
            // Co-op damage disabled?
            if(IS_NETGAME && !G_Ruleset_Deathmatch() && cfg.noCoopDamage)
                return 0;

            // Same color, no damage?
            if(cfg.noTeamDamage &&
               cfg.playerColor[target->player - players] ==
               cfg.playerColor[source->player - players])
                return 0;
        }
    }

    if(target->flags & MF_SKULLFLY)
    {
        target->mom[MX] = target->mom[MY] = target->mom[MZ] = 0;
    }

    player = target->player;
    if(player && G_Ruleset_Skill() == SM_BABY)
        damage /= 2; // Take half damage in trainer mode.

    // Use the cvar damage multiplier netMobDamageModifier only if the
    // inflictor is not a player.
    if(inflictor && !inflictor->player &&
       (!source || (source && !source->player)))
    {
        // damage = (int) ((float) damage * netMobDamageModifier);
        if(IS_NETGAME)
            damage *= cfg.netMobDamageModifier;
    }

    // Some close combat weapons should not inflict thrust and push the
    // victim out of reach, thus kick away unless using a melee weapon.
    if(inflictor && !(target->flags & MF_NOCLIP) &&
       (!source || !source->player ||
        source->player->readyWeapon != WT_EIGHTH) &&
       !(inflictor->flags2 & MF2_NODMGTHRUST))
    {
        uint an;
        coord_t thrust;

        angle = M_PointToAngle2(inflictor->origin, target->origin);
        thrust = FIX2FLT(damage * (FRACUNIT>>3) * 100 / target->info->mass);

        // Make fall forwards sometimes.
        if(damage < 40 && damage > target->health &&
           target->origin[VZ] - inflictor->origin[VZ] > 64 && (P_Random() & 1))
        {
            angle += ANG180;
            thrust *= 4;
        }

        an = angle >> ANGLETOFINESHIFT;
        target->mom[MX] += thrust * FIX2FLT(finecosine[an]);
        target->mom[MY] += thrust * FIX2FLT(finesine[an]);
        NetSv_PlayerMobjImpulse(target, thrust * FIX2FLT(finecosine[an]), thrust * FIX2FLT(finesine[an]), 0);

        // $dropoff_fix: thrust objects hanging off ledges.
        if((target->intFlags & MIF_FALLING) && target->gear >= MAXGEAR)
            target->gear = 0;
    }
Beispiel #5
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;
}
Beispiel #6
0
/**
 * Damages both enemies and players
 * Source and inflictor are the same for melee attacks.
 * Source can be NULL for slime, barrel explosions
 * and other environmental stuff.
 *
 * @param inflictor     Mobj that caused the damage creature or missile,
 *                      can be NULL (slime, etc).
 * @param source        Mobj to target after taking damage, creature or NULL.
 *
 * @return              Actual amount of damage done.
 */
int P_DamageMobj2(mobj_t *target, mobj_t *inflictor, mobj_t *source,
                  int damageP, dd_bool stomping, dd_bool skipNetworkCheck)
{
// Follow a player exlusively for 3 seconds.
#define BASETHRESHOLD           (100)

    uint an;
    angle_t angle;
    int saved;
    player_t *player;
    float thrust;
    //int temp;
    int originalHealth;

    // The actual damage (== damageP * netMobDamageModifier for any non-player mobj).
    int damage = damageP;

    if(!target)
        return 0; // Wha?

    originalHealth = target->health;

    if(!skipNetworkCheck)
    {
        // Clients can't harm anybody.
        if(IS_CLIENT)
            return 0;
    }

    if(!(target->flags & MF_SHOOTABLE))
        return 0; // Shouldn't happen...

    if(target->health <= 0)
        return 0;

    // Player specific.
    if(target->player)
    {
        // Check if player-player damage is disabled.
        if(source && source->player && source->player != target->player)
        {
            // Co-op damage disabled?
            if(IS_NETGAME && !G_Ruleset_Deathmatch() && cfg.noCoopDamage)
                return 0;

            // Same color, no damage?
            if(cfg.noTeamDamage &&
                    cfg.playerColor[target->player - players] ==
                    cfg.playerColor[source->player - players])
                return 0;
        }
    }

    if(target->flags & MF_SKULLFLY)
    {
        target->mom[MX] = target->mom[MY] = target->mom[MZ] = 0;
    }

    player = target->player;
    if(player && G_Ruleset_Skill() == SM_BABY)
        damage >>= 1; // take half damage in trainer mode

    // jd64 >
#if 0
    if(inflictor && inflictor->type == MT_FIREEND)
    {   // Special for Motherdemon attack
#if 0
        /** DJS - This was originally in a sub routine called P_TouchMotherFire
        *       but due to the fact that @c player, was not initialized
        *       this likely does not work the way kaiser expected it to.
        *       What would actually happen is not certain but I would guess it
        *       would most likely simply return without doing anything at all.
        * \todo SHOULD this be fixed? Or is something implemented elsewhere
        *       which does what this was attempting to do?
        */
        int         damage;
        player_t   *player;

        if(player = target->player)
        {
            damage = ((P_Random() % 10) + 1) * 8;

            P_DamageMobj(target, NULL, NULL, damage);
            player->plr->mo->momz = 16;
            player->jumpTics = 24;
        }
#endif
        return;
    }
#endif
    // < d64tc

    // Use the cvar damage multiplier netMobDamageModifier only if the
    // inflictor is not a player.
    if(inflictor && !inflictor->player &&
            (!source || (source && !source->player)))
    {
        // damage = (int) ((float) damage * netMobDamageModifier);
        if(IS_NETGAME)
            damage *= cfg.common.netMobDamageModifier;
    }

    // Some close combat weapons should not inflict thrust and push the
    // victim out of reach, thus kick away unless using the chainsaw.
    if(inflictor && !(target->flags & MF_NOCLIP) &&
            (!source || !source->player ||
             source->player->readyWeapon != WT_EIGHTH) &&
            !(inflictor->flags2 & MF2_NODMGTHRUST))
    {
        angle = M_PointToAngle2(inflictor->origin, target->origin);

        thrust = FIX2FLT(damage * (FRACUNIT>>3) * 100 / target->info->mass);

        // Make fall forwards sometimes.
        if(damage < 40 && damage > target->health &&
                target->origin[VZ] - inflictor->origin[VZ] > 64 && (P_Random() & 1))
        {
            angle += ANG180;
            thrust *= 4;
        }

        an = angle >> ANGLETOFINESHIFT;
        target->mom[MX] += thrust * FIX2FLT(finecosine[an]);
        target->mom[MY] += thrust * FIX2FLT(finesine[an]);
        NetSv_PlayerMobjImpulse(target, thrust * FIX2FLT(finecosine[an]), thrust * FIX2FLT(finesine[an]), 0);

        // $dropoff_fix: thrust objects hanging off ledges.
        if(target->intFlags & MIF_FALLING && target->gear >= MAXGEAR)
            target->gear = 0;
    }
Beispiel #7
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;
        }
    }
}