📄 gameutil.java
字号:
* Returns TRUE if an enemy was sighted * * When a player fires a missile, the point of impact becomes a fakeplayer * so that monsters that see the impact will respond as if they had seen the * player. * * To avoid spending too much time, only a single client (or fakeclient) is * checked each frame. This means multi player games will have slightly * slower noticing monsters. */ static boolean FindTarget(edict_t self) { edict_t client; boolean heardit; int r; if ((self.monsterinfo.aiflags & Defines.AI_GOOD_GUY) != 0) { if (self.goalentity != null && self.goalentity.inuse && self.goalentity.classname != null) { if (self.goalentity.classname.equals("target_actor")) return false; } //FIXME look for monsters? return false; } // if we're going to a combat point, just proceed if ((self.monsterinfo.aiflags & Defines.AI_COMBAT_POINT) != 0) return false; // if the first spawnflag bit is set, the monster will only wake up on // really seeing the player, not another monster getting angry or // hearing something // revised behavior so they will wake up if they "see" a player make a // noise but not weapon impact/explosion noises heardit = false; if ((GameBase.level.sight_entity_framenum >= (GameBase.level.framenum - 1)) && 0 == (self.spawnflags & 1)) { client = GameBase.level.sight_entity; if (client.enemy == self.enemy) return false; } else if (GameBase.level.sound_entity_framenum >= (GameBase.level.framenum - 1)) { client = GameBase.level.sound_entity; heardit = true; } else if (null != (self.enemy) && (GameBase.level.sound2_entity_framenum >= (GameBase.level.framenum - 1)) && 0 != (self.spawnflags & 1)) { client = GameBase.level.sound2_entity; heardit = true; } else { client = GameBase.level.sight_client; if (client == null) return false; // no clients to get mad at } // if the entity went away, forget it if (!client.inuse) return false; if (client.client != null) { if ((client.flags & Defines.FL_NOTARGET) != 0) return false; } else if ((client.svflags & Defines.SVF_MONSTER) != 0) { if (client.enemy == null) return false; if ((client.enemy.flags & Defines.FL_NOTARGET) != 0) return false; } else if (heardit) { if ((client.owner.flags & Defines.FL_NOTARGET) != 0) return false; } else return false; if (!heardit) { r = range(self, client); if (r == Defines.RANGE_FAR) return false; // this is where we would check invisibility // is client in an spot too dark to be seen? if (client.light_level <= 5) return false; if (!visible(self, client)) return false; if (r == Defines.RANGE_NEAR) { if (client.show_hostile < GameBase.level.time && !infront(self, client)) return false; } else if (r == Defines.RANGE_MID) { if (!infront(self, client)) return false; } if (client == self.enemy) return true; // JDC false; self.enemy = client; if (!self.enemy.classname.equals("player_noise")) { self.monsterinfo.aiflags &= ~Defines.AI_SOUND_TARGET; if (self.enemy.client == null) { self.enemy = self.enemy.enemy; if (self.enemy.client == null) { self.enemy = null; return false; } } } } else { // heard it float[] temp = { 0, 0, 0 }; if ((self.spawnflags & 1) != 0) { if (!visible(self, client)) return false; } else { if (!GameBase.gi.inPHS(self.s.origin, client.s.origin)) return false; } Math3D.VectorSubtract(client.s.origin, self.s.origin, temp); if (Math3D.VectorLength(temp) > 1000) // too far to hear return false; // check area portals - if they are different and not connected then // we can't hear it if (client.areanum != self.areanum) if (!GameBase.gi.AreasConnected(self.areanum, client.areanum)) return false; self.ideal_yaw = Math3D.vectoyaw(temp); M.M_ChangeYaw(self); // hunt the sound for a bit; hopefully find the real player self.monsterinfo.aiflags |= Defines.AI_SOUND_TARGET; if (client == self.enemy) return true; // JDC false; self.enemy = client; } // got one FoundTarget(self); if (0 == (self.monsterinfo.aiflags & Defines.AI_SOUND_TARGET) && (self.monsterinfo.sight != null)) self.monsterinfo.sight.interact(self, self.enemy); return true; } public static void FoundTarget(edict_t self) { // let other monsters see this monster for a while if (self.enemy.client != null) { GameBase.level.sight_entity = self; GameBase.level.sight_entity_framenum = GameBase.level.framenum; GameBase.level.sight_entity.light_level = 128; } self.show_hostile = (int) GameBase.level.time + 1; // wake up other // monsters Math3D.VectorCopy(self.enemy.s.origin, self.monsterinfo.last_sighting); self.monsterinfo.trail_time = GameBase.level.time; if (self.combattarget == null) { GameAI.HuntTarget(self); return; } self.goalentity = self.movetarget = GameBase .G_PickTarget(self.combattarget); if (self.movetarget == null) { self.goalentity = self.movetarget = self.enemy; GameAI.HuntTarget(self); GameBase.gi.dprintf("" + self.classname + "at " + Lib.vtos(self.s.origin) + ", combattarget " + self.combattarget + " not found\n"); return; } // clear out our combattarget, these are a one shot deal self.combattarget = null; self.monsterinfo.aiflags |= Defines.AI_COMBAT_POINT; // clear the targetname, that point is ours! self.movetarget.targetname = null; self.monsterinfo.pausetime = 0; // run for it self.monsterinfo.run.think(self); } public static EntThinkAdapter Think_Delay = new EntThinkAdapter() { public String getID() { return "Think_Delay"; } public boolean think(edict_t ent) { G_UseTargets(ent, ent.activator); G_FreeEdict(ent); return true; } }; public static EntThinkAdapter G_FreeEdictA = new EntThinkAdapter() { public String getID() { return "G_FreeEdictA"; } public boolean think(edict_t ent) { G_FreeEdict(ent); return false; } }; static EntThinkAdapter MegaHealth_think = new EntThinkAdapter() { public String getID() { return "MegaHealth_think"; } public boolean think(edict_t self) { if (self.owner.health > self.owner.max_health) { self.nextthink = GameBase.level.time + 1; self.owner.health -= 1; return false; } if (!((self.spawnflags & Defines.DROPPED_ITEM) != 0) && (GameBase.deathmatch.value != 0)) GameItems.SetRespawn(self, 20); else G_FreeEdict(self); return false; } }; public static EntThinkAdapter M_CheckAttack = new EntThinkAdapter() { public String getID() { return "M_CheckAttack"; } public boolean think(edict_t self) { float[] spot1 = { 0, 0, 0 }; float[] spot2 = { 0, 0, 0 }; float chance; trace_t tr; if (self.enemy.health > 0) { // see if any entities are in the way of the shot Math3D.VectorCopy(self.s.origin, spot1); spot1[2] += self.viewheight; Math3D.VectorCopy(self.enemy.s.origin, spot2); spot2[2] += self.enemy.viewheight; tr = GameBase.gi.trace(spot1, null, null, spot2, self, Defines.CONTENTS_SOLID | Defines.CONTENTS_MONSTER | Defines.CONTENTS_SLIME | Defines.CONTENTS_LAVA | Defines.CONTENTS_WINDOW); // do we have a clear shot? if (tr.ent != self.enemy) return false; } // melee attack if (GameAI.enemy_range == Defines.RANGE_MELEE) { // don't always melee in easy mode if (GameBase.skill.value == 0 && (Lib.rand() & 3) != 0) return false; if (self.monsterinfo.melee != null) self.monsterinfo.attack_state = Defines.AS_MELEE; else self.monsterinfo.attack_state = Defines.AS_MISSILE; return true; } // missile attack if (self.monsterinfo.attack == null) return false; if (GameBase.level.time < self.monsterinfo.attack_finished) return false; if (GameAI.enemy_range == Defines.RANGE_FAR) return false; if ((self.monsterinfo.aiflags & Defines.AI_STAND_GROUND) != 0) { chance = 0.4f; } else if (GameAI.enemy_range == Defines.RANGE_MELEE) { chance = 0.2f; } else if (GameAI.enemy_range == Defines.RANGE_NEAR) { chance = 0.1f; } else if (GameAI.enemy_range == Defines.RANGE_MID) { chance = 0.02f; } else { return false; } if (GameBase.skill.value == 0) chance *= 0.5; else if (GameBase.skill.value >= 2) chance *= 2; if (Lib.random() < chance) { self.monsterinfo.attack_state = Defines.AS_MISSILE; self.monsterinfo.attack_finished = GameBase.level.time + 2 * Lib.random(); return true; } if ((self.flags & Defines.FL_FLY) != 0) { if (Lib.random() < 0.3f) self.monsterinfo.attack_state = Defines.AS_SLIDING; else self.monsterinfo.attack_state = Defines.AS_STRAIGHT; } return false; } }; static EntUseAdapter monster_use = new EntUseAdapter() { public String getID() { return "monster_use"; } public void use(edict_t self, edict_t other, edict_t activator) { if (self.enemy != null) return; if (self.health <= 0) return; if ((activator.flags & Defines.FL_NOTARGET) != 0) return; if ((null == activator.client) && 0 == (activator.monsterinfo.aiflags & Defines.AI_GOOD_GUY)) return; // delay reaction so if the monster is teleported, its sound is // still heard self.enemy = activator; FoundTarget(self); } };}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -