コード例 #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
        /**
         * T_RadiusDamage.
         */
        public static void T_RadiusDamage(edict_t inflictor, edict_t attacker, float damage, edict_t ignore, float radius, int mod)
        {
            float         points;
            EdictIterator edictit = null;

            float[] v   = { 0, 0, 0 };
            float[] dir = { 0, 0, 0 };

            while ((edictit = GameBase.findradius(edictit, inflictor.s.origin, radius)) != null)
            {
                var ent = edictit.o;

                if (ent == ignore)
                {
                    continue;
                }

                if (ent.takedamage == 0)
                {
                    continue;
                }

                Math3D.VectorAdd(ent.mins, ent.maxs, v);
                Math3D.VectorMA(ent.s.origin, 0.5f, v, v);
                Math3D.VectorSubtract(inflictor.s.origin, v, v);
                points = damage - 0.5f * Math3D.VectorLength(v);

                if (ent == attacker)
                {
                    points = points * 0.5f;
                }

                if (points > 0)
                {
                    if (GameCombat.CanDamage(ent, inflictor))
                    {
                        Math3D.VectorSubtract(ent.s.origin, inflictor.s.origin, dir);

                        GameCombat.T_Damage(
                            ent,
                            inflictor,
                            attacker,
                            dir,
                            inflictor.s.origin,
                            Globals.vec3_origin,
                            (int)points,
                            (int)points,
                            Defines.DAMAGE_RADIUS,
                            mod
                            );
                    }
                }
            }
        }
コード例 #3
0
ファイル: GameUtil.cs プロジェクト: optimus-code/Quake2Sharp
        /**
         * Kills all entities that would touch the proposed new positioning of ent.
         * Ent should be unlinked before calling this!
         */
        public static bool KillBox(edict_t ent)
        {
            trace_t tr;

            while (true)
            {
                tr = GameBase.gi.trace(ent.s.origin, ent.mins, ent.maxs, ent.s.origin, null, Defines.MASK_PLAYERSOLID);

                if (tr.ent == null || tr.ent == GameBase.g_edicts[0])
                {
                    break;
                }

                // nail it
                GameCombat.T_Damage(
                    tr.ent,
                    ent,
                    ent,
                    Globals.vec3_origin,
                    ent.s.origin,
                    Globals.vec3_origin,
                    100000,
                    0,
                    Defines.DAMAGE_NO_PROTECTION,
                    Defines.MOD_TELEFRAG
                    );

                // if we didn't kill it, fail
                if (tr.ent.solid != 0)
                {
                    return(false);
                }
            }

            return(true);            // all clear
        }
コード例 #4
0
        /**
         * General effect handling for a player.
         */
        public static void P_WorldEffects()
        {
            bool breather;
            bool envirosuit;
            int  waterlevel, old_waterlevel;

            if (PlayerView.current_player.movetype == Defines.MOVETYPE_NOCLIP)
            {
                PlayerView.current_player.air_finished = GameBase.level.time + 12;                 // don't

                // need air
                return;
            }

            waterlevel     = PlayerView.current_player.waterlevel;
            old_waterlevel = PlayerView.current_client.old_waterlevel;
            PlayerView.current_client.old_waterlevel = waterlevel;

            breather   = PlayerView.current_client.breather_framenum > GameBase.level.framenum;
            envirosuit = PlayerView.current_client.enviro_framenum > GameBase.level.framenum;

            //
            // if just entered a water volume, play a sound
            //
            if (old_waterlevel == 0 && waterlevel != 0)
            {
                PlayerWeapon.PlayerNoise(PlayerView.current_player, PlayerView.current_player.s.origin, Defines.PNOISE_SELF);

                if ((PlayerView.current_player.watertype & Defines.CONTENTS_LAVA) != 0)
                {
                    GameBase.gi.sound(PlayerView.current_player, Defines.CHAN_BODY, GameBase.gi.soundindex("player/lava_in.wav"), 1, Defines.ATTN_NORM, 0);
                }
                else if ((PlayerView.current_player.watertype & Defines.CONTENTS_SLIME) != 0)
                {
                    GameBase.gi.sound(PlayerView.current_player, Defines.CHAN_BODY, GameBase.gi.soundindex("player/watr_in.wav"), 1, Defines.ATTN_NORM, 0);
                }
                else if ((PlayerView.current_player.watertype & Defines.CONTENTS_WATER) != 0)
                {
                    GameBase.gi.sound(PlayerView.current_player, Defines.CHAN_BODY, GameBase.gi.soundindex("player/watr_in.wav"), 1, Defines.ATTN_NORM, 0);
                }

                PlayerView.current_player.flags |= Defines.FL_INWATER;

                // clear damage_debounce, so the pain sound will play immediately
                PlayerView.current_player.damage_debounce_time = GameBase.level.time - 1;
            }

            //
            // if just completely exited a water volume, play a sound
            //
            if (old_waterlevel != 0 && waterlevel == 0)
            {
                PlayerWeapon.PlayerNoise(PlayerView.current_player, PlayerView.current_player.s.origin, Defines.PNOISE_SELF);
                GameBase.gi.sound(PlayerView.current_player, Defines.CHAN_BODY, GameBase.gi.soundindex("player/watr_out.wav"), 1, Defines.ATTN_NORM, 0);
                PlayerView.current_player.flags &= ~Defines.FL_INWATER;
            }

            //
            // check for head just going under water
            //
            if (old_waterlevel != 3 && waterlevel == 3)
            {
                GameBase.gi.sound(PlayerView.current_player, Defines.CHAN_BODY, GameBase.gi.soundindex("player/watr_un.wav"), 1, Defines.ATTN_NORM, 0);
            }

            //
            // check for head just coming out of water
            //
            if (old_waterlevel == 3 && waterlevel != 3)
            {
                if (PlayerView.current_player.air_finished < GameBase.level.time)
                {
                    // gasp for
                    // air
                    GameBase.gi.sound(PlayerView.current_player, Defines.CHAN_VOICE, GameBase.gi.soundindex("player/gasp1.wav"), 1, Defines.ATTN_NORM, 0);
                    PlayerWeapon.PlayerNoise(PlayerView.current_player, PlayerView.current_player.s.origin, Defines.PNOISE_SELF);
                }
                else if (PlayerView.current_player.air_finished < GameBase.level.time + 11)
                {
                    // just
                    // break
                    // surface
                    GameBase.gi.sound(PlayerView.current_player, Defines.CHAN_VOICE, GameBase.gi.soundindex("player/gasp2.wav"), 1, Defines.ATTN_NORM, 0);
                }
            }

            //
            // check for drowning
            //
            if (waterlevel == 3)
            {
                // breather or envirosuit give air
                if (breather || envirosuit)
                {
                    PlayerView.current_player.air_finished = GameBase.level.time + 10;

                    if ((int)(PlayerView.current_client.breather_framenum - GameBase.level.framenum) % 25 == 0)
                    {
                        if (PlayerView.current_client.breather_sound == 0)
                        {
                            GameBase.gi.sound(
                                PlayerView.current_player,
                                Defines.CHAN_AUTO,
                                GameBase.gi.soundindex("player/u_breath1.wav"),
                                1,
                                Defines.ATTN_NORM,
                                0
                                );
                        }
                        else
                        {
                            GameBase.gi.sound(
                                PlayerView.current_player,
                                Defines.CHAN_AUTO,
                                GameBase.gi.soundindex("player/u_breath2.wav"),
                                1,
                                Defines.ATTN_NORM,
                                0
                                );
                        }

                        PlayerView.current_client.breather_sound ^= 1;
                        PlayerWeapon.PlayerNoise(PlayerView.current_player, PlayerView.current_player.s.origin, Defines.PNOISE_SELF);

                        //FIXME: release a bubble?
                    }
                }

                // if out of air, start drowning
                if (PlayerView.current_player.air_finished < GameBase.level.time)
                {
                    // drown!
                    if (PlayerView.current_player.client.next_drown_time < GameBase.level.time && PlayerView.current_player.health > 0)
                    {
                        PlayerView.current_player.client.next_drown_time = GameBase.level.time + 1;

                        // take more damage the longer underwater
                        PlayerView.current_player.dmg += 2;

                        if (PlayerView.current_player.dmg > 15)
                        {
                            PlayerView.current_player.dmg = 15;
                        }

                        // play a gurp sound instead of a normal pain sound
                        if (PlayerView.current_player.health <= PlayerView.current_player.dmg)
                        {
                            GameBase.gi.sound(
                                PlayerView.current_player,
                                Defines.CHAN_VOICE,
                                GameBase.gi.soundindex("player/drown1.wav"),
                                1,
                                Defines.ATTN_NORM,
                                0
                                );
                        }
                        else if ((Lib.rand() & 1) != 0)
                        {
                            GameBase.gi.sound(PlayerView.current_player, Defines.CHAN_VOICE, GameBase.gi.soundindex("*gurp1.wav"), 1, Defines.ATTN_NORM, 0);
                        }
                        else
                        {
                            GameBase.gi.sound(PlayerView.current_player, Defines.CHAN_VOICE, GameBase.gi.soundindex("*gurp2.wav"), 1, Defines.ATTN_NORM, 0);
                        }

                        PlayerView.current_player.pain_debounce_time = GameBase.level.time;

                        GameCombat.T_Damage(
                            PlayerView.current_player,
                            GameBase.g_edicts[0],
                            GameBase.g_edicts[0],
                            Globals.vec3_origin,
                            PlayerView.current_player.s.origin,
                            Globals.vec3_origin,
                            PlayerView.current_player.dmg,
                            0,
                            Defines.DAMAGE_NO_ARMOR,
                            Defines.MOD_WATER
                            );
                    }
                }
            }
            else
            {
                PlayerView.current_player.air_finished = GameBase.level.time + 12;
                PlayerView.current_player.dmg          = 2;
            }

            //
            // check for sizzle damage
            //
            if (waterlevel != 0 && 0 != (PlayerView.current_player.watertype & (Defines.CONTENTS_LAVA | Defines.CONTENTS_SLIME)))
            {
                if ((PlayerView.current_player.watertype & Defines.CONTENTS_LAVA) != 0)
                {
                    if (PlayerView.current_player.health > 0 &&
                        PlayerView.current_player.pain_debounce_time <= GameBase.level.time &&
                        PlayerView.current_client.invincible_framenum < GameBase.level.framenum)
                    {
                        if ((Lib.rand() & 1) != 0)
                        {
                            GameBase.gi.sound(
                                PlayerView.current_player,
                                Defines.CHAN_VOICE,
                                GameBase.gi.soundindex("player/burn1.wav"),
                                1,
                                Defines.ATTN_NORM,
                                0
                                );
                        }
                        else
                        {
                            GameBase.gi.sound(
                                PlayerView.current_player,
                                Defines.CHAN_VOICE,
                                GameBase.gi.soundindex("player/burn2.wav"),
                                1,
                                Defines.ATTN_NORM,
                                0
                                );
                        }

                        PlayerView.current_player.pain_debounce_time = GameBase.level.time + 1;
                    }

                    if (envirosuit)                     // take 1/3 damage with envirosuit
                    {
                        GameCombat.T_Damage(
                            PlayerView.current_player,
                            GameBase.g_edicts[0],
                            GameBase.g_edicts[0],
                            Globals.vec3_origin,
                            PlayerView.current_player.s.origin,
                            Globals.vec3_origin,
                            1 * waterlevel,
                            0,
                            0,
                            Defines.MOD_LAVA
                            );
                    }
                    else
                    {
                        GameCombat.T_Damage(
                            PlayerView.current_player,
                            GameBase.g_edicts[0],
                            GameBase.g_edicts[0],
                            Globals.vec3_origin,
                            PlayerView.current_player.s.origin,
                            Globals.vec3_origin,
                            3 * waterlevel,
                            0,
                            0,
                            Defines.MOD_LAVA
                            );
                    }
                }

                if ((PlayerView.current_player.watertype & Defines.CONTENTS_SLIME) != 0)
                {
                    if (!envirosuit)
                    {
                        // no damage from slime with envirosuit
                        GameCombat.T_Damage(
                            PlayerView.current_player,
                            GameBase.g_edicts[0],
                            GameBase.g_edicts[0],
                            Globals.vec3_origin,
                            PlayerView.current_player.s.origin,
                            Globals.vec3_origin,
                            1 * waterlevel,
                            0,
                            0,
                            Defines.MOD_SLIME
                            );
                    }
                }
            }
        }
コード例 #5
0
        /**
         * Calculates damage and effect when a player falls down.
         */
        public static void P_FallingDamage(edict_t ent)
        {
            float delta;
            int   damage;

            float[] dir = { 0, 0, 0 };

            if (ent.s.modelindex != 255)
            {
                return;                 // not in the player model
            }
            if (ent.movetype == Defines.MOVETYPE_NOCLIP)
            {
                return;
            }

            if (ent.client.oldvelocity[2] < 0 && ent.velocity[2] > ent.client.oldvelocity[2] && null == ent.groundentity)
            {
                delta = ent.client.oldvelocity[2];
            }
            else
            {
                if (ent.groundentity == null)
                {
                    return;
                }

                delta = ent.velocity[2] - ent.client.oldvelocity[2];
            }

            delta = delta * delta * 0.0001f;

            // never take falling damage if completely underwater
            if (ent.waterlevel == 3)
            {
                return;
            }

            if (ent.waterlevel == 2)
            {
                delta *= 0.25f;
            }

            if (ent.waterlevel == 1)
            {
                delta *= 0.5f;
            }

            if (delta < 1)
            {
                return;
            }

            if (delta < 15)
            {
                ent.s.@event = Defines.EV_FOOTSTEP;

                return;
            }

            ent.client.fall_value = delta * 0.5f;

            if (ent.client.fall_value > 40)
            {
                ent.client.fall_value = 40;
            }

            ent.client.fall_time = GameBase.level.time + Defines.FALL_TIME;

            if (delta > 30)
            {
                if (ent.health > 0)
                {
                    if (delta >= 55)
                    {
                        ent.s.@event = Defines.EV_FALLFAR;
                    }
                    else
                    {
                        ent.s.@event = Defines.EV_FALL;
                    }
                }

                ent.pain_debounce_time = GameBase.level.time;                 // no normal pain

                // sound
                damage = (int)((delta - 30) / 2);

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

                Math3D.VectorSet(dir, 0, 0, 1);

                if (GameBase.deathmatch.value == 0 || 0 == ((int)GameBase.dmflags.value & Defines.DF_NO_FALLING))
                {
                    GameCombat.T_Damage(
                        ent,
                        GameBase.g_edicts[0],
                        GameBase.g_edicts[0],
                        dir,
                        ent.s.origin,
                        Globals.vec3_origin,
                        damage,
                        0,
                        0,
                        Defines.MOD_FALLING
                        );
                }
            }
            else
            {
                ent.s.@event = Defines.EV_FALLSHORT;

                return;
            }
        }
コード例 #6
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);
            }
        }
コード例 #7
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);
        }