Example #1
0
        public static void T_Damage(
            edict_t targ,
            edict_t inflictor,
            edict_t attacker,
            float[] dir,
            float[] point,
            float[] normal,
            int damage,
            int knockback,
            int dflags,
            int mod
            )
        {
            gclient_t client;
            int       take;
            int       save;
            int       asave;
            int       psave;
            int       te_sparks;

            if (targ.takedamage == 0)
            {
                return;
            }

            // friendly fire avoidance
            // if enabled you can't hurt teammates (but you can hurt yourself)
            // knockback still occurs
            if (targ != attacker &&
                ((GameBase.deathmatch.value != 0 && 0 != ((int)GameBase.dmflags.value & (Defines.DF_MODELTEAMS | Defines.DF_SKINTEAMS))) ||
                 GameBase.coop.value != 0))
            {
                if (GameUtil.OnSameTeam(targ, attacker))
                {
                    if (((int)GameBase.dmflags.value & Defines.DF_NO_FRIENDLY_FIRE) != 0)
                    {
                        damage = 0;
                    }
                    else
                    {
                        mod |= Defines.MOD_FRIENDLY_FIRE;
                    }
                }
            }

            GameBase.meansOfDeath = mod;

            // easy mode takes half damage
            if (GameBase.skill.value == 0 && GameBase.deathmatch.value == 0 && targ.client != null)
            {
                damage /= 2;

                if (damage == 0)
                {
                    damage = 1;
                }
            }

            client = targ.client;

            if ((dflags & Defines.DAMAGE_BULLET) != 0)
            {
                te_sparks = Defines.TE_BULLET_SPARKS;
            }
            else
            {
                te_sparks = Defines.TE_SPARKS;
            }

            Math3D.VectorNormalize(dir);

            // bonus damage for suprising a monster
            if (0 == (dflags & Defines.DAMAGE_RADIUS) &&
                (targ.svflags & Defines.SVF_MONSTER) != 0 &&
                attacker.client != null &&
                targ.enemy == null &&
                targ.health > 0)
            {
                damage *= 2;
            }

            if ((targ.flags & Defines.FL_NO_KNOCKBACK) != 0)
            {
                knockback = 0;
            }

            // figure momentum add
            if (0 == (dflags & Defines.DAMAGE_NO_KNOCKBACK))
            {
                if (knockback != 0 &&
                    targ.movetype != Defines.MOVETYPE_NONE &&
                    targ.movetype != Defines.MOVETYPE_BOUNCE &&
                    targ.movetype != Defines.MOVETYPE_PUSH &&
                    targ.movetype != Defines.MOVETYPE_STOP)
                {
                    float[] kvel = { 0, 0, 0 };
                    float   mass;

                    if (targ.mass < 50)
                    {
                        mass = 50;
                    }
                    else
                    {
                        mass = targ.mass;
                    }

                    if (targ.client != null && attacker == targ)
                    {
                        Math3D.VectorScale(dir, 1600.0f * (float)knockback / mass, kvel);
                    }

                    // the rocket jump hack...
                    else
                    {
                        Math3D.VectorScale(dir, 500.0f * (float)knockback / mass, kvel);
                    }

                    Math3D.VectorAdd(targ.velocity, kvel, targ.velocity);
                }
            }

            take = damage;
            save = 0;

            // check for godmode
            if ((targ.flags & Defines.FL_GODMODE) != 0 && 0 == (dflags & Defines.DAMAGE_NO_PROTECTION))
            {
                take = 0;
                save = damage;
                GameCombat.SpawnDamage(te_sparks, point, normal, save);
            }

            // check for invincibility
            if (client != null && client.invincible_framenum > GameBase.level.framenum && 0 == (dflags & Defines.DAMAGE_NO_PROTECTION))
            {
                if (targ.pain_debounce_time < GameBase.level.time)
                {
                    GameBase.gi.sound(targ, Defines.CHAN_ITEM, GameBase.gi.soundindex("items/protect4.wav"), 1, Defines.ATTN_NORM, 0);
                    targ.pain_debounce_time = GameBase.level.time + 2;
                }

                take = 0;
                save = damage;
            }

            psave = GameCombat.CheckPowerArmor(targ, point, normal, take, dflags);
            take -= psave;

            asave = GameCombat.CheckArmor(targ, point, normal, take, te_sparks, dflags);
            take -= asave;

            // treat cheat/powerup savings the same as armor
            asave += save;

            // team damage avoidance
            if (0 == (dflags & Defines.DAMAGE_NO_PROTECTION) && GameCombat.CheckTeamDamage(targ, attacker))
            {
                return;
            }

            // do the damage
            if (take != 0)
            {
                if (0 != (targ.svflags & Defines.SVF_MONSTER) || client != null)
                {
                    GameCombat.SpawnDamage(Defines.TE_BLOOD, point, normal, take);
                }
                else
                {
                    GameCombat.SpawnDamage(te_sparks, point, normal, take);
                }

                targ.health = targ.health - take;

                if (targ.health <= 0)
                {
                    if ((targ.svflags & Defines.SVF_MONSTER) != 0 || client != null)
                    {
                        targ.flags |= Defines.FL_NO_KNOCKBACK;
                    }

                    GameCombat.Killed(targ, inflictor, attacker, take, point);

                    return;
                }
            }

            if ((targ.svflags & Defines.SVF_MONSTER) != 0)
            {
                GameCombat.M_ReactToDamage(targ, attacker);

                if (0 == (targ.monsterinfo.aiflags & Defines.AI_DUCKED) && take != 0)
                {
                    targ.pain.pain(targ, attacker, knockback, take);

                    // nightmare mode monsters don't go into pain frames often
                    if (GameBase.skill.value == 3)
                    {
                        targ.pain_debounce_time = GameBase.level.time + 5;
                    }
                }
            }
            else if (client != null)
            {
                if ((targ.flags & Defines.FL_GODMODE) == 0 && take != 0)
                {
                    targ.pain.pain(targ, attacker, knockback, take);
                }
            }
            else if (take != 0)
            {
                if (targ.pain != null)
                {
                    targ.pain.pain(targ, attacker, knockback, take);
                }
            }

            // add to the damage inflicted on a player this frame
            // the total will be turned into screen blends and view angle kicks
            // at the end of the frame
            if (client != null)
            {
                client.damage_parmor    += psave;
                client.damage_armor     += asave;
                client.damage_blood     += take;
                client.damage_knockback += knockback;
                Math3D.VectorCopy(point, client.damage_from);
            }
        }