Example #1
0
        public static edict_t PickFirst(edict_t self)
        {
            if (!PlayerTrail.trail_active)
            {
                return(null);
            }

            var marker = PlayerTrail.trail_head;

            for (var n = PlayerTrail.TRAIL_LENGTH; n > 0; n--)
            {
                if (PlayerTrail.trail[marker].timestamp <= self.monsterinfo.trail_time)
                {
                    marker = PlayerTrail.NEXT(marker);
                }
                else
                {
                    break;
                }
            }

            if (GameUtil.visible(self, PlayerTrail.trail[marker]))
            {
                return(PlayerTrail.trail[marker]);
            }

            if (GameUtil.visible(self, PlayerTrail.trail[PlayerTrail.PREV(marker)]))
            {
                return(PlayerTrail.trail[PlayerTrail.PREV(marker)]);
            }

            return(PlayerTrail.trail[marker]);
        }
Example #2
0
        public static void M_ReactToDamage(edict_t targ, edict_t attacker)
        {
            if (null != attacker.client && 0 != (attacker.svflags & Defines.SVF_MONSTER))
            {
                return;
            }

            if (attacker == targ || attacker == targ.enemy)
            {
                return;
            }

            // if we are a good guy monster and our attacker is a player
            // or another good guy, do not get mad at them
            if (0 != (targ.monsterinfo.aiflags & Defines.AI_GOOD_GUY))
            {
                if (attacker.client != null || (attacker.monsterinfo.aiflags & Defines.AI_GOOD_GUY) != 0)
                {
                    return;
                }
            }

            // we now know that we are not both good guys

            // if attacker is a client, get mad at them because he's good and we're
            // not
            if (attacker.client != null)
            {
                targ.monsterinfo.aiflags &= ~Defines.AI_SOUND_TARGET;

                // this can only happen in coop (both new and old enemies are
                // clients)
                // only switch if can't see the current enemy
                if (targ.enemy != null && targ.enemy.client != null)
                {
                    if (GameUtil.visible(targ, targ.enemy))
                    {
                        targ.oldenemy = attacker;

                        return;
                    }

                    targ.oldenemy = targ.enemy;
                }

                targ.enemy = attacker;

                if (0 == (targ.monsterinfo.aiflags & Defines.AI_DUCKED))
                {
                    GameUtil.FoundTarget(targ);
                }

                return;
            }

            // it's the same base (walk/swim/fly) type and a different classname and
            // it's not a tank
            // (they spray too much), get mad at them
            if ((targ.flags & (Defines.FL_FLY | Defines.FL_SWIM)) == (attacker.flags & (Defines.FL_FLY | Defines.FL_SWIM)) &&
                !targ.classname.Equals(attacker.classname) &&
                !attacker.classname.Equals("monster_tank") &&
                !attacker.classname.Equals("monster_supertank") &&
                !attacker.classname.Equals("monster_makron") &&
                !attacker.classname.Equals("monster_jorg"))
            {
                if (targ.enemy != null && targ.enemy.client != null)
                {
                    targ.oldenemy = targ.enemy;
                }

                targ.enemy = attacker;

                if (0 == (targ.monsterinfo.aiflags & Defines.AI_DUCKED))
                {
                    GameUtil.FoundTarget(targ);
                }
            }

            // if they *meant* to shoot us, then shoot back
            else if (attacker.enemy == targ)
            {
                if (targ.enemy != null && targ.enemy.client != null)
                {
                    targ.oldenemy = targ.enemy;
                }

                targ.enemy = attacker;

                if (0 == (targ.monsterinfo.aiflags & Defines.AI_DUCKED))
                {
                    GameUtil.FoundTarget(targ);
                }
            }

            // otherwise get mad at whoever they are mad at (help our buddy) unless
            // it is us!
            else if (attacker.enemy != null && attacker.enemy != targ)
            {
                if (targ.enemy != null && targ.enemy.client != null)
                {
                    targ.oldenemy = targ.enemy;
                }

                targ.enemy = attacker.enemy;

                if (0 == (targ.monsterinfo.aiflags & Defines.AI_DUCKED))
                {
                    GameUtil.FoundTarget(targ);
                }
            }
        }
Example #3
0
        /**
         * Decides if we're going to attack or do something else used by ai_run and
         * ai_stand.
         *
         * .enemy Will be world if not currently angry at anyone.
         *
         * .movetarget The next path spot to walk toward. If .enemy, ignore
         * .movetarget. When an enemy is killed, the monster will try to return to
         * it's path.
         *
         * .hunt_time Set to time + something when the player is in sight, but
         * movement straight for him is blocked. This causes the monster to use wall
         * following code for movement direction instead of sighting on the player.
         *
         * .ideal_yaw A yaw angle of the intended direction, which will be turned
         * towards at up to 45 deg / state. If the enemy is in view and hunt_time is
         * not active, this will be the exact line towards the enemy.
         *
         * .pausetime A monster will leave it's stand state and head towards it's
         * .movetarget when time > .pausetime.
         *
         * walkmove(angle, speed) primitive is all or nothing
         */
        public static bool ai_checkattack(edict_t self, float dist)
        {
            float[] temp = { 0, 0, 0 };

            bool hesDeadJim;

            // this causes monsters to run blindly to the combat point w/o firing
            if (self.goalentity != null)
            {
                if ((self.monsterinfo.aiflags & Defines.AI_COMBAT_POINT) != 0)
                {
                    return(false);
                }

                if ((self.monsterinfo.aiflags & Defines.AI_SOUND_TARGET) != 0)
                {
                    if (GameBase.level.time - self.enemy.teleport_time > 5.0)
                    {
                        if (self.goalentity == self.enemy)
                        {
                            if (self.movetarget != null)
                            {
                                self.goalentity = self.movetarget;
                            }
                            else
                            {
                                self.goalentity = null;
                            }
                        }

                        self.monsterinfo.aiflags &= ~Defines.AI_SOUND_TARGET;

                        if ((self.monsterinfo.aiflags & Defines.AI_TEMP_STAND_GROUND) != 0)
                        {
                            self.monsterinfo.aiflags &= ~(Defines.AI_STAND_GROUND | Defines.AI_TEMP_STAND_GROUND);
                        }
                    }
                    else
                    {
                        self.show_hostile = (int)GameBase.level.time + 1;

                        return(false);
                    }
                }
            }

            GameAI.enemy_vis = false;

            // see if the enemy is dead
            hesDeadJim = false;

            if (null == self.enemy || !self.enemy.inuse)
            {
                hesDeadJim = true;
            }
            else if ((self.monsterinfo.aiflags & Defines.AI_MEDIC) != 0)
            {
                if (self.enemy.health > 0)
                {
                    hesDeadJim = true;
                    self.monsterinfo.aiflags &= ~Defines.AI_MEDIC;
                }
            }
            else
            {
                if ((self.monsterinfo.aiflags & Defines.AI_BRUTAL) != 0)
                {
                    if (self.enemy.health <= -80)
                    {
                        hesDeadJim = true;
                    }
                }
                else
                {
                    if (self.enemy.health <= 0)
                    {
                        hesDeadJim = true;
                    }
                }
            }

            if (hesDeadJim)
            {
                self.enemy = null;

                // FIXME: look all around for other targets
                if (self.oldenemy != null && self.oldenemy.health > 0)
                {
                    self.enemy    = self.oldenemy;
                    self.oldenemy = null;
                    GameAI.HuntTarget(self);
                }
                else
                {
                    if (self.movetarget != null)
                    {
                        self.goalentity = self.movetarget;
                        self.monsterinfo.walk.think(self);
                    }
                    else
                    {
                        // we need the pausetime otherwise the stand code
                        // will just revert to walking with no target and
                        // the monsters will wonder around aimlessly trying
                        // to hunt the world entity
                        self.monsterinfo.pausetime = GameBase.level.time + 100000000;
                        self.monsterinfo.stand.think(self);
                    }

                    return(true);
                }
            }

            self.show_hostile = (int)GameBase.level.time + 1;             // wake up other

            // monsters check knowledge of enemy
            GameAI.enemy_vis = GameUtil.visible(self, self.enemy);

            if (GameAI.enemy_vis)
            {
                self.monsterinfo.search_time = GameBase.level.time + 5;
                Math3D.VectorCopy(self.enemy.s.origin, self.monsterinfo.last_sighting);
            }

            GameAI.enemy_infront = GameUtil.infront(self, self.enemy);
            GameAI.enemy_range   = GameUtil.range(self, self.enemy);
            Math3D.VectorSubtract(self.enemy.s.origin, self.s.origin, temp);
            GameAI.enemy_yaw = Math3D.vectoyaw(temp);

            // JDC self.ideal_yaw = enemy_yaw;

            if (self.monsterinfo.attack_state == Defines.AS_MISSILE)
            {
                GameAI.ai_run_missile(self);

                return(true);
            }

            if (self.monsterinfo.attack_state == Defines.AS_MELEE)
            {
                GameAI.ai_run_melee(self);

                return(true);
            }

            // if enemy is not currently visible, we will never attack
            if (!GameAI.enemy_vis)
            {
                return(false);
            }

            return(self.monsterinfo.checkattack.think(self));
        }