Пример #1
0
        private static int CheckArmor(edict_t ent, float[] point, float[] normal, int damage, int te_sparks, int dflags)
        {
            gclient_t client;
            int       save;
            int       index;
            gitem_t   armor;

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

            client = ent.client;

            if (client == null)
            {
                return(0);
            }

            if ((dflags & Defines.DAMAGE_NO_ARMOR) != 0)
            {
                return(0);
            }

            index = GameItems.ArmorIndex(ent);

            if (index == 0)
            {
                return(0);
            }

            armor = GameItems.GetItemByIndex(index);
            var garmor = (gitem_armor_t)armor.info;

            if (0 != (dflags & Defines.DAMAGE_ENERGY))
            {
                save = (int)Math.Ceiling(garmor.energy_protection * damage);
            }
            else
            {
                save = (int)Math.Ceiling(garmor.normal_protection * damage);
            }

            if (save >= client.pers.inventory[index])
            {
                save = client.pers.inventory[index];
            }

            if (save == 0)
            {
                return(0);
            }

            client.pers.inventory[index] -= save;
            GameCombat.SpawnDamage(te_sparks, point, normal, save);

            return(save);
        }
Пример #2
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);
            }
        }
Пример #3
0
        private static int CheckPowerArmor(edict_t ent, float[] point, float[] normal, int damage, int dflags)
        {
            gclient_t client;
            int       save;
            int       power_armor_type;
            var       index = 0;
            int       damagePerCell;
            int       pa_te_type;
            var       power = 0;
            int       power_used;

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

            client = ent.client;

            if ((dflags & Defines.DAMAGE_NO_ARMOR) != 0)
            {
                return(0);
            }

            if (client != null)
            {
                power_armor_type = GameItems.PowerArmorType(ent);

                if (power_armor_type != Defines.POWER_ARMOR_NONE)
                {
                    index = GameItems.ITEM_INDEX(GameItems.FindItem("Cells"));
                    power = client.pers.inventory[index];
                }
            }
            else if ((ent.svflags & Defines.SVF_MONSTER) != 0)
            {
                power_armor_type = ent.monsterinfo.power_armor_type;
                power            = ent.monsterinfo.power_armor_power;
            }
            else
            {
                return(0);
            }

            if (power_armor_type == Defines.POWER_ARMOR_NONE)
            {
                return(0);
            }

            if (power == 0)
            {
                return(0);
            }

            if (power_armor_type == Defines.POWER_ARMOR_SCREEN)
            {
                float[] vec = { 0, 0, 0 };
                float   dot;
                float[] forward = { 0, 0, 0 };

                // only works if damage point is in front
                Math3D.AngleVectors(ent.s.angles, forward, null, null);
                Math3D.VectorSubtract(point, ent.s.origin, vec);
                Math3D.VectorNormalize(vec);
                dot = Math3D.DotProduct(vec, forward);

                if (dot <= 0.3)
                {
                    return(0);
                }

                damagePerCell = 1;
                pa_te_type    = Defines.TE_SCREEN_SPARKS;
                damage        = damage / 3;
            }
            else
            {
                damagePerCell = 2;
                pa_te_type    = Defines.TE_SHIELD_SPARKS;
                damage        = 2 * damage / 3;
            }

            save = power * damagePerCell;

            if (save == 0)
            {
                return(0);
            }

            if (save > damage)
            {
                save = damage;
            }

            GameCombat.SpawnDamage(pa_te_type, point, normal, save);
            ent.powerarmor_time = GameBase.level.time + 0.2f;

            power_used = save / damagePerCell;

            if (client != null)
            {
                client.pers.inventory[index] -= power_used;
            }
            else
            {
                ent.monsterinfo.power_armor_power -= power_used;
            }

            return(save);
        }