예제 #1
0
        /**
         * Turn in place until within an angle to launch a missile attack.
         */
        public static void ai_run_missile(edict_t self)
        {
            self.ideal_yaw = GameAI.enemy_yaw;
            M.M_ChangeYaw(self);

            if (GameAI.FacingIdeal(self))
            {
                self.monsterinfo.attack.think(self);
                self.monsterinfo.attack_state = Defines.AS_STRAIGHT;
            }
        }
예제 #2
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));
        }