⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gameai.java

📁 Jake2是一个Java 3D游戏引擎.
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1997-2001 Id Software, Inc. *  * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. *  * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. *  * See the GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. *   */// Created on 02.11.2003 by RST.// $Id: GameAI.java,v 1.10 2005/12/27 21:02:30 salomo Exp $package jake2.game;import jake2.Defines;import jake2.Globals;import jake2.client.M;import jake2.util.Lib;import jake2.util.Math3D;public class GameAI {    public static void AttackFinished(edict_t self, float time) {        self.monsterinfo.attack_finished = GameBase.level.time + time;    }    /** Don't move, but turn towards ideal_yaw Distance is for slight position     * adjustments needed by the animations.     */    public static void ai_turn(edict_t self, float dist) {        if (dist != 0)            M.M_walkmove(self, self.s.angles[Defines.YAW], dist);        if (GameUtil.FindTarget(self))            return;        M.M_ChangeYaw(self);    }        /**      * Checks, if the monster should turn left/right.     */    public static boolean FacingIdeal(edict_t self) {        float delta;        delta = Math3D.anglemod(self.s.angles[Defines.YAW] - self.ideal_yaw);        if (delta > 45 && delta < 315)            return false;        return true;    }    /**     * Turn and close until within an angle to launch a melee attack.     */    public static void ai_run_melee(edict_t self) {        self.ideal_yaw = enemy_yaw;        M.M_ChangeYaw(self);        if (FacingIdeal(self)) {            self.monsterinfo.melee.think(self);            self.monsterinfo.attack_state = Defines.AS_STRAIGHT;        }    }    /**     * Turn in place until within an angle to launch a missile attack.     */    public static void ai_run_missile(edict_t self) {        self.ideal_yaw = enemy_yaw;        M.M_ChangeYaw(self);        if (FacingIdeal(self)) {            self.monsterinfo.attack.think(self);            self.monsterinfo.attack_state = Defines.AS_STRAIGHT;        }    };    /**     * Strafe sideways, but stay at aproximately the same range.     */    public static void ai_run_slide(edict_t self, float distance) {        float ofs;        self.ideal_yaw = enemy_yaw;        M.M_ChangeYaw(self);        if (self.monsterinfo.lefty != 0)            ofs = 90;        else            ofs = -90;        if (M.M_walkmove(self, self.ideal_yaw + ofs, distance))            return;        self.monsterinfo.lefty = 1 - self.monsterinfo.lefty;        M.M_walkmove(self, self.ideal_yaw - ofs, distance);    }    /**     * 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 boolean ai_checkattack(edict_t self, float dist) {        float temp[] = { 0, 0, 0 };        boolean 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;                }            }        }        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;                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        enemy_vis = GameUtil.visible(self, self.enemy);        if (enemy_vis) {            self.monsterinfo.search_time = GameBase.level.time + 5;            Math3D.VectorCopy(self.enemy.s.origin,                    self.monsterinfo.last_sighting);        }        enemy_infront = GameUtil.infront(self, self.enemy);        enemy_range = GameUtil.range(self, self.enemy);        Math3D.VectorSubtract(self.enemy.s.origin, self.s.origin, temp);        enemy_yaw = Math3D.vectoyaw(temp);        // JDC self.ideal_yaw = enemy_yaw;        if (self.monsterinfo.attack_state == Defines.AS_MISSILE) {            ai_run_missile(self);            return true;        }        if (self.monsterinfo.attack_state == Defines.AS_MELEE) {            ai_run_melee(self);            return true;        }        // if enemy is not currently visible, we will never attack        if (!enemy_vis)            return false;        return self.monsterinfo.checkattack.think(self);    }    /**     * The monster is walking it's beat.     */    static void ai_walk(edict_t self, float dist) {        M.M_MoveToGoal(self, dist);            // check for noticing a player        if (GameUtil.FindTarget(self))            return;            if ((self.monsterinfo.search != null)                && (GameBase.level.time > self.monsterinfo.idle_time)) {            if (self.monsterinfo.idle_time != 0) {                self.monsterinfo.search.think(self);                self.monsterinfo.idle_time = GameBase.level.time + 15                        + Lib.random() * 15;            } else {                self.monsterinfo.idle_time = GameBase.level.time + Lib.random()                        * 15;            }        }    }    /**     * Called once each frame to set level.sight_client to the player to be     * checked for in findtarget.     *      * If all clients are either dead or in notarget, sight_client will be null.     *      * In coop games, sight_client will cycle between the clients.     */    static void AI_SetSightClient() {        edict_t ent;        int start, check;            if (GameBase.level.sight_client == null)            start = 1;        else            start = GameBase.level.sight_client.index;            check = start;        while (true) {            check++;            if (check > GameBase.game.maxclients)                check = 1;            ent = GameBase.g_edicts[check];                if (ent.inuse && ent.health > 0                    && (ent.flags & Defines.FL_NOTARGET) == 0) {                GameBase.level.sight_client = ent;                return; // got one            }            if (check == start) {                GameBase.level.sight_client = null;                return; // nobody to see            }        }    }    /**     * Move the specified distance at current facing. This replaces the QC     * functions: ai_forward, ai_back, ai_pain, and ai_painforward     */    static void ai_move(edict_t self, float dist) {        M.M_walkmove(self, self.s.angles[Defines.YAW], dist);    }     /**     * Decides running or standing according to flag AI_STAND_GROUND.     */    static void HuntTarget(edict_t self) {        float[] vec = { 0, 0, 0 };            self.goalentity = self.enemy;        if ((self.monsterinfo.aiflags & Defines.AI_STAND_GROUND) != 0)            self.monsterinfo.stand.think(self);        else            self.monsterinfo.run.think(self);        Math3D.VectorSubtract(self.enemy.s.origin, self.s.origin, vec);        self.ideal_yaw = Math3D.vectoyaw(vec);                // wait a while before first attack        if (0 == (self.monsterinfo.aiflags & Defines.AI_STAND_GROUND))            GameUtil.AttackFinished(self, 1);    }        public static EntThinkAdapter walkmonster_start_go = new EntThinkAdapter() {        public String getID() { return "walkmonster_start_go"; }        public boolean think(edict_t self) {            if (0 == (self.spawnflags & 2) && GameBase.level.time < 1) {                M.M_droptofloor.think(self);                if (self.groundentity != null)                    if (!M.M_walkmove(self, 0, 0))                        GameBase.gi.dprintf(self.classname + " in solid at "                                + Lib.vtos(self.s.origin) + "\n");            }            if (0 == self.yaw_speed)                self.yaw_speed = 40;            self.viewheight = 25;            Monster.monster_start_go(self);            if ((self.spawnflags & 2) != 0)                Monster.monster_triggered_start.think(self);            return true;        }    };    public static EntThinkAdapter walkmonster_start = new EntThinkAdapter() {        public String getID() { return "walkmonster_start";}                 public boolean think(edict_t self) {            self.think = walkmonster_start_go;            Monster.monster_start(self);            return true;        }    };    public static EntThinkAdapter flymonster_start_go = new EntThinkAdapter() {        public String getID() { return "flymonster_start_go";}        public boolean think(edict_t self) {            if (!M.M_walkmove(self, 0, 0))                GameBase.gi.dprintf(self.classname + " in solid at "                        + Lib.vtos(self.s.origin) + "\n");            if (0 == self.yaw_speed)                self.yaw_speed = 20;            self.viewheight = 25;            Monster.monster_start_go(self);            if ((self.spawnflags & 2) != 0)                Monster.monster_triggered_start.think(self);            return true;        }    };    public static EntThinkAdapter flymonster_start = new EntThinkAdapter() {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -