Example #1
0
static int numAmmoClipsToGiveWithWeapon(dd_bool dropped)
{
    // Dropped weapons only ever give one clip.
    if(dropped) return 1;

    // Give extra clips in deathmatch.
    return (IS_NETGAME && G_Ruleset_Deathmatch() == 1)? 5 : 2;
}
Example #2
0
static dd_bool giveOneWeapon(player_t *plr, weapontype_t weaponType, dd_bool dropped)
{
    int numClips = numAmmoClipsToGiveWithWeapon(dropped);
    dd_bool gaveAmmo = false, gaveWeapon = false;
    weaponinfo_t const *wpnInfo;
    ammotype_t i;

    DENG_ASSERT(plr != 0);
    DENG_ASSERT(weaponType >= WT_FIRST && weaponType < NUM_WEAPON_TYPES);

    wpnInfo = &weaponInfo[weaponType][plr->class_];

    // Do not give weapons unavailable for the current mode.
    if(!(wpnInfo->mode[0].gameModeBits & gameModeBits))
        return false;

    // Give some of each of the ammo types used by this weapon.
    for(i = 0; i < NUM_AMMO_TYPES; ++i)
    {
        // Is this ammo type usable?.
        if(!wpnInfo->mode[0].ammoType[i])
            continue;

        if(P_GiveAmmo(plr, i, numClips))
        {
            gaveAmmo = true;
        }
    }

    if(!plr->weapons[weaponType].owned)
    {
        gaveWeapon = true;

        plr->weapons[weaponType].owned = true;
        plr->update |= PSF_OWNED_WEAPONS;

        // Animate a pickup bonus flash?
        if(IS_NETGAME && G_Ruleset_Deathmatch() != 2 && !dropped)
        {
            plr->bonusCount += BONUSADD;
        }

        // Given the new weapon the player may want to change automatically.
        P_MaybeChangeWeapon(plr, weaponType, AT_NOAMMO,
                            shouldForceWeaponChange(dropped));

        // Maybe unhide the HUD?
        ST_HUDUnHide(plr - players, HUE_ON_PICKUP_WEAPON);
    }

    return (gaveWeapon || gaveAmmo);
}
Example #3
0
/**
 * Attempt to pickup the found weapon type.
 *
 * @param plr            Player to attempt the pickup.
 * @param weaponType     Weapon type to pickup.
 * @param dropped        @c true= the weapon was dropped by someone.
 * @param pickupMessage  Message to display if picked up.
 *
 * @return  @c true if the player picked up the weapon.
 */
static dd_bool pickupWeapon(player_t *plr, weapontype_t weaponType,
    dd_bool dropped, char const *pickupMessage)
{
    dd_bool pickedWeapon;

    DENG_ASSERT(plr != 0);
    DENG_ASSERT(weaponType >= WT_FIRST && weaponType < NUM_WEAPON_TYPES);

    // Depending on the game rules the player should ignore the weapon.
    if(plr->weapons[weaponType].owned)
    {
        // Leave placed weapons forever on net games.
        if(IS_NETGAME && G_Ruleset_Deathmatch() != 2 && !dropped)
            return false;
    }

    // Attempt the pickup.
    pickedWeapon = P_GiveWeapon(plr, weaponType, dropped);
    if(pickedWeapon)
    {
        // Notify the user.
        P_SetMessage(plr, 0, pickupMessage);

        if(!mapSetup) // Pickup sounds are not played during map setup.
        {
            S_ConsoleSound(SFX_WPNUP, NULL, plr - players);
        }
    }

    if(IS_NETGAME && G_Ruleset_Deathmatch() != 2 && !dropped)
    {
        // Leave placed weapons forever on net games.
        return false;
    }

    return pickedWeapon;
}
Example #4
0
static dd_bool shouldForceWeaponChange(dd_bool dropped)
{
    return IS_NETGAME && G_Ruleset_Deathmatch() == 1 && !dropped;
}
Example #5
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;
    }
Example #6
0
/**
 * The weapon name may have a MF_DROPPED flag ored in.
 */
dd_bool P_GiveWeapon(player_t *player, weapontype_t weapon, dd_bool dropped)
{
    ammotype_t i;
    dd_bool gaveAmmo = false;
    dd_bool gaveWeapon;
    int numClips;

    if(IS_NETGAME && (G_Ruleset_Deathmatch() != 2) && !dropped)
    {
        // leave placed weapons forever on net games
        if(player->weapons[weapon].owned)
            return false;

        player->bonusCount += BONUSADD;
        player->weapons[weapon].owned = true;
        player->update |= PSF_OWNED_WEAPONS;

        // Give some of each of the ammo types used by this weapon.
        for(i = 0; i < NUM_AMMO_TYPES; ++i)
        {
            if(!weaponInfo[weapon][player->class_].mode[0].ammoType[i])
                continue; // Weapon does not take this type of ammo.

            if(G_Ruleset_Deathmatch())
                numClips = 5;
            else
                numClips = 2;

            if(P_GiveAmmo(player, i, numClips))
                gaveAmmo = true; // At least ONE type of ammo was given.
        }

        // Should we change weapon automatically?
        P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, G_Ruleset_Deathmatch() == 1);

        // Maybe unhide the HUD?
        ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON);

        S_ConsoleSound(SFX_WPNUP, NULL, player - players);
        return false;
    }
    else
    {
        // Give some of each of the ammo types used by this weapon.
        for(i = 0; i < NUM_AMMO_TYPES; ++i)
        {
            if(!weaponInfo[weapon][player->class_].mode[0].ammoType[i])
                continue;   // Weapon does not take this type of ammo.

            // Give one clip with a dropped weapon, two clips with a found
            // weapon.
            if(dropped)
                numClips = 1;
            else
                numClips = 2;

            if(P_GiveAmmo(player, i, numClips))
                gaveAmmo = true; // At least ONE type of ammo was given.
        }

        if(player->weapons[weapon].owned)
            gaveWeapon = false;
        else
        {
            gaveWeapon = true;
            player->weapons[weapon].owned = true;
            player->update |= PSF_OWNED_WEAPONS;

            // Should we change weapon automatically?
            P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, false);
        }

        // Maybe unhide the HUD?
        if(gaveWeapon)
            ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON);

        return (gaveWeapon || gaveAmmo);
    }
}
Example #7
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;
    }