]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'Mario/intrusive' into 'master'
authorTimePath <andrew.hardaker1995@gmail.com>
Sat, 27 Aug 2016 00:36:20 +0000 (00:36 +0000)
committerTimePath <andrew.hardaker1995@gmail.com>
Sat, 27 Aug 2016 00:36:20 +0000 (00:36 +0000)
Merge branch Mario/intrusive (XL merge request)

Ports a few more FOREACH_ENTITY_* loops to the new intrusive lists system, further restoring the performance lost by the pure entities.

See merge request !361

90 files changed:
qcsrc/client/view.qc
qcsrc/common/effects/qc/rubble.qh
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/gamemodes/gamemode/onslaught/cl_controlpoint.qc
qcsrc/common/gamemodes/gamemode/onslaught/cl_generator.qc
qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qh
qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc
qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qh
qcsrc/common/monsters/monster/mage.qc
qcsrc/common/monsters/monster/shambler.qc
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/monsters/monster/wyvern.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/itemstime/itemstime.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/overkill/rpc.qc
qcsrc/common/mutators/mutator/sandbox/sv_sandbox.qc
qcsrc/common/mutators/mutator/sandbox/sv_sandbox.qh
qcsrc/common/notifications/all.qc
qcsrc/common/notifications/all.qh
qcsrc/common/t_items.qc
qcsrc/common/triggers/func/breakable.qc
qcsrc/common/triggers/func/conveyor.qc
qcsrc/common/triggers/func/conveyor.qh
qcsrc/common/triggers/func/door_secret.qc
qcsrc/common/triggers/target/music.qc
qcsrc/common/triggers/teleporters.qc
qcsrc/common/triggers/teleporters.qh
qcsrc/common/triggers/trigger/teleport.qc
qcsrc/common/turrets/sv_turrets.qc
qcsrc/common/turrets/targettrigger.qc
qcsrc/common/turrets/turret/phaser_weapon.qc
qcsrc/common/turrets/turret/walker.qc
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/vehicles/sv_vehicles.qh
qcsrc/common/vehicles/vehicle/raptor_weapons.qc
qcsrc/common/vehicles/vehicle/spiderbot.qc
qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/blaster.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/fireball.qc
qcsrc/common/weapons/weapon/hagar.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/hook.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/mortar.qc
qcsrc/common/weapons/weapon/porto.qc
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/lib/net.qh
qcsrc/server/bot/api.qh
qcsrc/server/bot/default/bot.qc
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/havocbot/roles.qc
qcsrc/server/bot/default/havocbot/roles.qh
qcsrc/server/bot/default/navigation.qc
qcsrc/server/bot/default/scripting.qc
qcsrc/server/bot/default/waypoints.qc
qcsrc/server/bot/null/bot_null.qc
qcsrc/server/cheats.qc
qcsrc/server/client.qc
qcsrc/server/client.qh
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_hook.qc
qcsrc/server/g_world.qc
qcsrc/server/impulse.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/mutator/gamemode_assault.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qc
qcsrc/server/mutators/mutator/gamemode_cts.qc
qcsrc/server/mutators/mutator/gamemode_domination.qc
qcsrc/server/mutators/mutator/gamemode_domination.qh
qcsrc/server/mutators/mutator/gamemode_invasion.qc
qcsrc/server/mutators/mutator/gamemode_keepaway.qc
qcsrc/server/mutators/mutator/gamemode_keyhunt.qc
qcsrc/server/mutators/mutator/gamemode_race.qc
qcsrc/server/player.qc
qcsrc/server/race.qc
qcsrc/server/race.qh
qcsrc/server/spawnpoints.qc
qcsrc/server/sv_main.qc
qcsrc/server/t_quake3.qc
qcsrc/server/weapons/selection.qc

index 7780c522ddb5ba43b8fd9471797dfbfb3d2e8824..8a583ba699ee74e5443c1afd1456eca77740d02c 100644 (file)
@@ -1507,9 +1507,10 @@ void CSQC_UpdateView(entity this, float w, float h)
                        }
                }
 
-               if(ons_roundlost)
+               if(ons_roundlost) // TODO: move this junk to a client mutator for onslaught (possible using the WantEventchase hook)
                {
-                       FOREACH_ENTITY_CLASS("onslaught_generator", it.health <= 0, {
+                       IL_EACH(g_onsgenerators, it.health <= 0,
+                       {
                                gen = it;
                                break;
                        });
index 83a6941213d627dbeca64e0174cc9e662696310e..dd3785b68ea2cf65af3fb5ecc5c77f86c0b102e0 100644 (file)
@@ -5,7 +5,10 @@
 entityclass(Rubble);
 class(Rubble).float creationtime;
 
-void RubbleLimit(string cname, float limit, void(entity) deleteproc)
+IntrusiveList g_rubble;
+STATIC_INIT(g_rubble) { g_rubble = IL_NEW(); }
+
+void RubbleLimit(string cname, int limit, void(entity) deleteproc)
 {
        // remove rubble of the same type if it's at the limit
        // remove multiple rubble if the limit has been decreased
@@ -17,7 +20,7 @@ void RubbleLimit(string cname, float limit, void(entity) deleteproc)
                entity oldest = NULL;
                float oldesttime = 0;
                // compare to all other matching entities
-               FOREACH_ENTITY_CLASS(cname, true,
+               IL_EACH(g_rubble, it.classname == cname,
                {
                        ++c;
                        if(!oldest || oldesttime > it.creationtime)
@@ -41,6 +44,7 @@ entity RubbleNew(string cname)
        entity e = spawn();
        e.classname = cname;
        e.creationtime = time;
+       IL_PUSH(g_rubble, e);
        return e;
 }
 
index 9c6c9f0803941379bb39e765980cd4bc6361b133..0054fd63607b1523c5b729382e1fe52c593da6d9 100644 (file)
@@ -835,6 +835,7 @@ void W_Nexball_Attack2(entity actor, .entity weaponentity)
        missile.effects = EF_BRIGHTFIELD | EF_LOWPRECISION;
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
 
        CSQCProjectile(missile, true, PROJECTILE_ELECTRO, true);
 }
index fb8cb71719a2e4acea5a10718a737eb4f54d50bb..ee348fdbc6244707f53e7b6202aae30cd6392ea7 100644 (file)
@@ -104,7 +104,7 @@ void cpicon_damage(entity this, float hp)
        setsize(this, CPICON_MIN, CPICON_MAX);
 }
 
-void cpicon_construct(entity this)
+void cpicon_construct(entity this, bool isnew)
 {
        this.netname = "Control Point Icon";
 
@@ -133,6 +133,9 @@ void cpicon_construct(entity this)
        this.cp_origin          = this.origin;
        this.cp_bob_origin      = '0 0 0.1';
        this.cp_bob_spd         = 0;
+
+       if(isnew)
+               IL_PUSH(g_drawables, this);
 }
 
 .vector glowmod;
@@ -174,7 +177,7 @@ NET_HANDLE(ENT_CLIENT_CONTROLPOINT_ICON, bool isnew)
                        this.count = (this.health - this.max_health) * frametime;
 
                cpicon_changeteam(this);
-               cpicon_construct(this);
+               cpicon_construct(this, isnew);
        }
 
        if(sf & CPSF_STATUS)
index 2b9470f7750ab2b9fecac82a5abe51590811e6bb..cbba9a9aaa87bc23d183b18b224f9fd508d91080 100644 (file)
@@ -143,11 +143,14 @@ void generator_damage(entity this, float hp)
        setsize(this, GENERATOR_MIN, GENERATOR_MAX);
 }
 
-void generator_construct(entity this)
+void generator_construct(entity this, bool isnew)
 {
        this.netname = "Generator";
        this.classname = "onslaught_generator";
 
+       if(isnew)
+               IL_PUSH(g_onsgenerators, this);
+
        setorigin(this, this.origin);
        setmodel(this, MDL_ONS_GEN);
        setsize(this, GENERATOR_MIN, GENERATOR_MAX);
@@ -199,7 +202,7 @@ NET_HANDLE(ENT_CLIENT_GENERATOR, bool isnew)
                        this.count = 40;
 
                generator_changeteam(this);
-               generator_construct(this);
+               generator_construct(this, isnew);
        }
 
        if(sf & GSF_STATUS)
index be9b8203c61e60db594ea0579506e2c4ad9ca5f5..c863e2f71fb264d25ba52809ad1f2edaa87d59ad 100644 (file)
@@ -2,3 +2,13 @@
 
 REGISTER_NET_LINKED(ENT_CLIENT_GENERATOR)
 REGISTER_NET_LINKED(ENT_CLIENT_CONTROLPOINT_ICON)
+
+#ifdef SVQC
+IntrusiveList g_onsshields;
+STATIC_INIT(g_onsshields) { g_onsshields = IL_NEW(); }
+#endif
+
+#ifdef CSQC
+IntrusiveList g_onsgenerators;
+STATIC_INIT(g_onsgenerators) { g_onsgenerators = IL_NEW(); }
+#endif
index 570bc3645fdbbe1104e201b0a2a94fce3a410e44..8e60bc30897a4ac897ea19c594630b68987989a3 100644 (file)
@@ -74,6 +74,7 @@ void ons_CaptureShield_Reset(entity this)
 void ons_CaptureShield_Spawn(entity generator, bool is_generator)
 {
        entity shield = new(ons_captureshield);
+       IL_PUSH(g_onsshields, shield);
 
        shield.enemy = generator;
        shield.team = generator.team;
@@ -195,12 +196,16 @@ void onslaught_updatelinks()
                {
                        LOG_DEBUG(etos(l), " (generator) is shielded");
                        l.takedamage = DAMAGE_NO;
+                       if(l.bot_attack)
+                               IL_REMOVE(g_bot_targets, l);
                        l.bot_attack = false;
                }
                else
                {
                        LOG_DEBUG(etos(l), " (generator) is not shielded");
                        l.takedamage = DAMAGE_AIM;
+                       if(!l.bot_attack)
+                               IL_PUSH(g_bot_targets, l);
                        l.bot_attack = true;
                }
 
@@ -215,6 +220,8 @@ void onslaught_updatelinks()
                        if (l.goalentity)
                        {
                                l.goalentity.takedamage = DAMAGE_NO;
+                               if(l.goalentity.bot_attack)
+                                       IL_REMOVE(g_bot_targets, l.goalentity);
                                l.goalentity.bot_attack = false;
                        }
                }
@@ -224,12 +231,14 @@ void onslaught_updatelinks()
                        if (l.goalentity)
                        {
                                l.goalentity.takedamage = DAMAGE_AIM;
+                               if(!l.goalentity.bot_attack)
+                                       IL_PUSH(g_bot_targets, l.goalentity);
                                l.goalentity.bot_attack = true;
                        }
                }
                ons_ControlPoint_UpdateSprite(l);
        }
-       FOREACH_ENTITY_CLASS("ons_captureshield", true,
+       IL_EACH(g_onsshields, true,
        {
                it.team = it.enemy.team;
                it.colormap = it.enemy.colormap;
@@ -565,6 +574,7 @@ void ons_ControlPoint_Icon_Spawn(entity cp, entity player)
        e.solid = SOLID_NOT;
        e.takedamage = DAMAGE_AIM;
        e.bot_attack = true;
+       IL_PUSH(g_bot_targets, e);
        e.event_damage = ons_ControlPoint_Icon_Damage;
        e.team = player.team;
        e.colormap = 1024 + (e.team - 1) * 17;
@@ -916,6 +926,7 @@ void ons_GeneratorReset(entity this)
        this.lasthealth = this.max_health = this.health = autocvar_g_onslaught_gen_health;
        this.takedamage = DAMAGE_AIM;
        this.bot_attack = true;
+       IL_PUSH(g_bot_targets, this);
        this.iscaptured = true;
        this.islinked = true;
        this.isshielded = true;
@@ -978,6 +989,7 @@ void ons_GeneratorSetup(entity gen) // called when spawning a generator entity o
        gen.lasthealth = gen.max_health = gen.health = autocvar_g_onslaught_gen_health;
        gen.takedamage = DAMAGE_AIM;
        gen.bot_attack = true;
+       IL_PUSH(g_bot_targets, gen);
        gen.event_damage = ons_GeneratorDamage;
        gen.reset = ons_GeneratorReset;
        setthink(gen, ons_GeneratorThink);
@@ -1182,7 +1194,7 @@ void havocbot_goalrating_ons_offenseitems(entity this, float ratingscale, vector
        LOG_DEBUG(this.netname, " needs armor ", ftos(needarmor));
 
        // See what is around
-       FOREACH_ENTITY_FLOAT(bot_pickup, true,
+       IL_EACH(g_items, it.bot_pickup,
        {
                // gather health and armor only
                if (it.solid)
@@ -1463,21 +1475,21 @@ void havocbot_ons_reset_role(entity this)
 entity ons_Nearest_ControlPoint(entity this, vector pos, float max_dist)
 {
        entity closest_target = NULL;
-       FOREACH_ENTITY_CLASS("onslaught_controlpoint", true,
+       for(entity cp = ons_worldcplist; cp; cp = cp.ons_worldcpnext)
        {
-               if(SAME_TEAM(it, this))
-               if(it.iscaptured)
-               if(max_dist <= 0 || vdist(it.origin - pos, <=, max_dist))
-               if(vlen2(it.origin - pos) <= vlen2(closest_target.origin - pos) || closest_target == NULL)
-                       closest_target = it;
-       });
-       FOREACH_ENTITY_CLASS("onslaught_generator", true,
+               if(SAME_TEAM(cp, this))
+               if(cp.iscaptured)
+               if(max_dist <= 0 || vdist(cp.origin - pos, <=, max_dist))
+               if(vlen2(cp.origin - pos) <= vlen2(closest_target.origin - pos) || closest_target == NULL)
+                       closest_target = cp;
+       }
+       for(entity gen = ons_worldgeneratorlist; gen; gen = gen.ons_worldgeneratornext)
        {
-               if(SAME_TEAM(it, this))
-               if(max_dist <= 0 || vdist(it.origin - pos, <, max_dist))
-               if(vlen2(it.origin - pos) <= vlen2(closest_target.origin - pos) || closest_target == NULL)
-                       closest_target = it;
-       });
+               if(SAME_TEAM(gen, this))
+               if(max_dist <= 0 || vdist(gen.origin - pos, <, max_dist))
+               if(vlen2(gen.origin - pos) <= vlen2(closest_target.origin - pos) || closest_target == NULL)
+                       closest_target = gen;
+       }
 
        return closest_target;
 }
@@ -1493,35 +1505,35 @@ entity ons_Nearest_ControlPoint_2D(entity this, vector pos, float max_dist)
        vector delta;
        float smallest_distance = 0, distance;
 
-       FOREACH_ENTITY_CLASS("onslaught_controlpoint", true,
+       for(entity cp = ons_worldcplist; cp; cp = cp.ons_worldcpnext)
        {
-               delta = it.origin - pos;
+               delta = cp.origin - pos;
                delta_z = 0;
                distance = vlen(delta);
 
-               if(SAME_TEAM(it, this))
-               if(it.iscaptured)
+               if(SAME_TEAM(cp, this))
+               if(cp.iscaptured)
                if(max_dist <= 0 || distance <= max_dist)
                if(closest_target == NULL || distance <= smallest_distance )
                {
-                       closest_target = it;
+                       closest_target = cp;
                        smallest_distance = distance;
                }
-       });
-       FOREACH_ENTITY_CLASS("onslaught_generator", true,
+       }
+       for(entity gen = ons_worldgeneratorlist; gen; gen = gen.ons_worldgeneratornext)
        {
-               delta = it.origin - pos;
+               delta = gen.origin - pos;
                delta_z = 0;
                distance = vlen(delta);
 
-               if(SAME_TEAM(it, this))
+               if(SAME_TEAM(gen, this))
                if(max_dist <= 0 || distance <= max_dist)
                if(closest_target == NULL || distance <= smallest_distance )
                {
-                       closest_target = it;
+                       closest_target = gen;
                        smallest_distance = distance;
                }
-       });
+       }
 
        return closest_target;
 }
@@ -1531,17 +1543,17 @@ entity ons_Nearest_ControlPoint_2D(entity this, vector pos, float max_dist)
 int ons_Count_SelfControlPoints(entity this)
 {
        int n = 0;
-       FOREACH_ENTITY_CLASS("onslaught_controlpoint", true,
+       for(entity cp = ons_worldcplist; cp; cp = cp.ons_worldcpnext)
        {
-               if(SAME_TEAM(it, this))
-               if(it.iscaptured)
+               if(SAME_TEAM(cp, this))
+               if(cp.iscaptured)
                        n++;
-       });
-       FOREACH_ENTITY_CLASS("onslaught_generator", true,
+       }
+       for(entity gen = ons_worldgeneratorlist; gen; gen = gen.ons_worldgeneratornext)
        {
-               if(SAME_TEAM(it, this))
+               if(SAME_TEAM(gen, this))
                        n++;
-       });
+       }
        return n;
 }
 
index 70a5c8b6ba999078cb459c8933e2c11f7ab660e8..750ade34b412ece9a6b8a868c4cc747367407ae1 100644 (file)
@@ -44,7 +44,6 @@ const vector CPICON_OFFSET = ('0 0 96');
 // list of generators on the map
 entity ons_worldgeneratorlist;
 .entity ons_worldgeneratornext;
-.entity ons_stalegeneratornext;
 
 // list of control points on the map
 entity ons_worldcplist;
index 650999de1eaf4c7c63e7b295d6b5a6143ed94fb7..628f3e5eaa71f474a6bb070cd047becf405e6051 100644 (file)
@@ -201,6 +201,7 @@ void M_Mage_Attack_Spike(entity this, vector dir)
        set_movetype(missile, MOVETYPE_FLYMISSILE);
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
        setorigin(missile, this.origin + v_forward * 14 + '0 0 30' + v_right * -14);
        setsize(missile, '0 0 0', '0 0 0');
        missile.velocity = dir * 400;
@@ -382,10 +383,9 @@ METHOD(Mage, mr_think, bool(Mage thismon, entity actor))
     TC(Mage, thismon);
     bool need_help = false;
 
-    FOREACH_ENTITY_FLOAT(iscreature, true,
+    FOREACH_CLIENT(IS_PLAYER(it) && it != actor,
     {
-        if(it != actor)
-        if(vdist(it.origin - actor.origin, <=, autocvar_g_monster_mage_heal_range))
+       if(vdist(it.origin - actor.origin, <=, autocvar_g_monster_mage_heal_range))
         if(M_Mage_Defend_Heal_Check(actor, it))
         {
             need_help = true;
@@ -393,6 +393,19 @@ METHOD(Mage, mr_think, bool(Mage thismon, entity actor))
         }
     });
 
+    if(!need_help)
+    {
+       IL_EACH(g_monsters, it != actor,
+       {
+               if(vdist(it.origin - actor.origin, <=, autocvar_g_monster_mage_heal_range))
+               if(M_Mage_Defend_Heal_Check(actor, it))
+               {
+                   need_help = true;
+                   break;
+               }
+       });
+    }
+
     if(actor.health < (autocvar_g_monster_mage_heal_minhealth) || need_help)
     if(time >= actor.attack_finished_single[0])
     if(random() < 0.5)
index 3ba01fe21f226005c15b0bc04d59084e0b923938..1abe2e9c8700af6156ce8bbcfb78e87a726b4863 100644 (file)
@@ -150,6 +150,7 @@ void M_Shambler_Attack_Lightning(entity this)
        gren.angles = vectoangles (gren.velocity);
        gren.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, gren);
+       IL_PUSH(g_bot_dodge, gren);
 
        CSQCProjectile(gren, true, PROJECTILE_SHAMBLER_LIGHTNING, true);
 }
index 43a07e650c419a08f7675279f79df203f0ca517c..4a0c29a1717fa934127a44153c01670d2c48006d 100644 (file)
@@ -161,6 +161,7 @@ void M_Spider_Attack_Web(entity this)
        proj.event_damage = func_null;
        proj.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, proj);
+       IL_PUSH(g_bot_dodge, proj);
        proj.damagedbycontents = true;
 
        proj.bouncefactor = 0.3;
index 48e7ad61dce690da511c00b1cc5191bd3e0f0d2c..a05b462a0e6e54ea1cde2b01519fbf4017622bf8 100644 (file)
@@ -36,6 +36,7 @@ METHOD(WyvernAttack, wr_think, void(WyvernAttack thiswep, entity actor, .entity
                setorigin(missile, actor.origin + actor.view_ofs + v_forward * 14);
                missile.flags = FL_PROJECTILE;
         IL_PUSH(g_projectiles, missile);
+        IL_PUSH(g_bot_dodge, missile);
                missile.velocity = w_shotdir * (autocvar_g_monster_wyvern_attack_fireball_speed);
                missile.avelocity = '300 300 300';
                missile.nextthink = time + 5;
@@ -74,10 +75,9 @@ void M_Wyvern_Attack_Fireball_Explode(entity this)
 
        RadiusDamage(this, own, autocvar_g_monster_wyvern_attack_fireball_damage, autocvar_g_monster_wyvern_attack_fireball_edgedamage, autocvar_g_monster_wyvern_attack_fireball_force, NULL, NULL, autocvar_g_monster_wyvern_attack_fireball_radius, this.projectiledeathtype, NULL);
 
-       FOREACH_ENTITY_FLOAT(takedamage, DAMAGE_AIM,
+       FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_monster_wyvern_attack_fireball_radius, it.takedamage == DAMAGE_AIM,
        {
-               if(vdist(it.origin - this.origin, <=, autocvar_g_monster_wyvern_attack_fireball_radius))
-                       Fire_AddDamage(it, own, 5 * MONSTER_SKILLMOD(own), autocvar_g_monster_wyvern_attack_fireball_damagetime, this.projectiledeathtype);
+               Fire_AddDamage(it, own, 5 * MONSTER_SKILLMOD(own), autocvar_g_monster_wyvern_attack_fireball_damagetime, this.projectiledeathtype);
        });
 
        delete(this);
index a4f7e6acaace738772fd366d81f499b57a4cdf7c..1fbb410da064669374ffd81e47eb7089c548c46f 100644 (file)
@@ -1324,6 +1324,7 @@ bool Monster_Spawn(entity this, int mon_id)
        this.classname                  = "monster";
        this.takedamage                 = DAMAGE_AIM;
        this.bot_attack                 = true;
+       IL_PUSH(g_bot_targets, this);
        this.iscreature                 = true;
        this.teleportable               = true;
        this.damagedbycontents  = true;
index d9223b302a13b771f34e11b55c8bb7077e08f01c..73f6b63935f6999fc47cda077473659c5634220b 100644 (file)
@@ -345,6 +345,10 @@ void buff_Init(entity this)
        this.classname = "item_buff";
        this.solid = SOLID_TRIGGER;
        this.flags = FL_ITEM;
+       this.bot_pickup = true;
+       this.bot_pickupevalfunc = commodity_pickupevalfunc;
+       this.bot_pickupbasevalue = 1000;
+       IL_PUSH(g_items, this);
        setthink(this, buff_Think);
        settouch(this, buff_Touch);
        this.reset = buff_Reset;
@@ -822,7 +826,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
        if(player.buffs & BUFF_MAGNET.m_itemid)
        {
                vector pickup_size;
-               FOREACH_ENTITY_FLAGS(flags, FL_ITEM,
+               IL_EACH(g_items, true,
                {
                        if(it.buffs)
                                pickup_size = '1 1 1' * autocvar_g_buffs_magnet_range_buff;
index 1252c34ed75c3fab38ab84286146186c99931bf7..b76d22e95b51e5a1409a365159ab1e2261136c33 100644 (file)
@@ -137,11 +137,10 @@ void Item_ItemsTime_SetTimesForAllPlayers()
 float Item_ItemsTime_UpdateTime(entity e, float t)
 {
     bool isavailable = (t == 0);
-    FOREACH_ENTITY_FLOAT(pure_data, false,
+    IL_EACH(g_items, it != e,
     {
-        if(!(it.itemdef == e.itemdef || ((e.weapons & WEPSET_SUPERWEAPONS) && (it.weapons & WEPSET_SUPERWEAPONS) && clienttype(it) == CLIENTTYPE_NOTACLIENT)))
+        if(!(it.itemdef == e.itemdef || ((e.weapons & WEPSET_SUPERWEAPONS) && (it.weapons & WEPSET_SUPERWEAPONS))))
             continue;
-        if (e == it) continue;
         if (it.scheduledrespawntime <= time)
             isavailable = true;
         else if (t == 0 || it.scheduledrespawntime < t)
@@ -157,11 +156,9 @@ MUTATOR_HOOKFUNCTION(itemstime, reset_map_global)
     Item_ItemsTime_ResetTimes();
     // ALL the times need to be reset before .reset()ing each item
     // since Item_Reset schedules respawn of superweapons and powerups
-    FOREACH_ENTITY_FLOAT(pure_data, false,
+    IL_EACH(g_items, it.reset,
     {
-        if(IS_CLIENT(it))
-            continue;
-        if (it.reset) Item_ItemsTime_SetTime(it, 0);
+        Item_ItemsTime_SetTime(it, 0);
     });
     Item_ItemsTime_SetTimesForAllPlayers();
 }
index d15353745e694868381c0aaf589e015c697c78ad..c8114694f547bb09f82a331ee2c9c45c30111121 100644 (file)
@@ -293,6 +293,7 @@ void nade_napalm_ball(entity this)
        proj.angles = vectoangles(proj.velocity);
        proj.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, proj);
+       IL_PUSH(g_bot_dodge, proj);
        proj.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_ARC;
 
        //CSQCProjectile(proj, true, PROJECTILE_NAPALM_FIRE, true);
@@ -349,6 +350,9 @@ void nade_napalm_boom(entity this)
        fountain.owner = this.owner;
        fountain.realowner = this.realowner;
        fountain.origin = this.origin;
+       fountain.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, fountain);
+       IL_PUSH(g_bot_dodge, fountain);
        setorigin(fountain, fountain.origin);
        setthink(fountain, napalm_fountain_think);
        fountain.nextthink = time;
@@ -730,10 +734,9 @@ void nade_boom(entity this)
                case NADE_TYPE_ENTRAP: nade_entrap_boom(this); break;
        }
 
-       FOREACH_ENTITY_ENT(aiment, this,
+       IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
        {
-               if(it.classname == "grapplinghook")
-                       RemoveGrapplingHook(it.realowner);
+               RemoveGrapplingHook(it.realowner);
        });
 
        delete(this);
@@ -780,10 +783,9 @@ void nade_touch(entity this, entity toucher)
                is_weapclip = 1;*/
        if(ITEM_TOUCH_NEEDKILL()) // || is_weapclip)
        {
-               FOREACH_ENTITY_ENT(aiment, this,
+               IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
                {
-                       if(it.classname == "grapplinghook")
-                               RemoveGrapplingHook(it.realowner);
+                       RemoveGrapplingHook(it.realowner);
                });
                delete(this);
                return;
@@ -942,6 +944,7 @@ void toss_nade(entity e, bool set_owner, vector _velocity, float _time)
        _nade.angles = vectoangles(_nade.velocity);
        _nade.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, _nade);
+       IL_PUSH(g_bot_dodge, _nade);
        _nade.projectiledeathtype = DEATH_NADE.m_id;
        _nade.toss_time = time;
        _nade.solid = SOLID_CORPSE; //((_nade.nade_type == NADE_TYPE_TRANSLOCATE) ? SOLID_CORPSE : SOLID_BBOX);
index 4540a26f2e626ccc4761536b0b0cabc0d95e474d..122bdfc12c49bb43c89c6bb522352d18e1382b2e 100644 (file)
@@ -97,6 +97,7 @@ void W_RocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .entity wea
        missile.nextthink = time;
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
 
        CSQCProjectile(missile, true, PROJECTILE_RPC, false);
 
index d0739c2e4443a4e2e1820079bb7a6a7eb581dbb1..a2211fe75a2af294e229af70cafa403837c4a9df 100644 (file)
@@ -143,12 +143,9 @@ void sandbox_ObjectAttach_Remove(entity e)
 {
        // detaches any object attached to e
 
-       FOREACH_ENTITY_ENT(owner, e,
+       IL_EACH(g_sandbox_objects, it.owner == e,
        {
-               if(it.classname != "object") continue;
-
-               vector org;
-               org = gettaginfo(it, 0);
+               vector org = gettaginfo(it, 0);
                setattachment(it, NULL, "");
                it.owner = NULL;
 
@@ -167,6 +164,7 @@ entity sandbox_ObjectSpawn(entity this, float database)
        // spawn a new object with default properties
 
        entity e = new(object);
+       IL_PUSH(g_sandbox_objects, e);
        e.takedamage = DAMAGE_AIM;
        e.damageforcescale = 1;
        e.solid = SOLID_BBOX; // SOLID_BSP would be best, but can lag the server badly
@@ -226,30 +224,28 @@ void sandbox_ObjectRemove(entity e)
 
 string port_string[MAX_STORAGE_ATTACHMENTS]; // fteqcc crashes if this isn't defined as a global
 
-string sandbox_ObjectPort_Save(entity e, float database)
+string sandbox_ObjectPort_Save(entity e, bool database)
 {
        // save object properties, and return them as a string
-       float i = 0;
-       string s;
-       entity head;
+       int o = 0;
 
-       for(head = NULL; (head = find(head, classname, "object")); )
-       {
+       // order doesn't really matter, as we're writing the file fresh
+       IL_EACH(g_sandbox_objects, it == e || it.owner == e, LAMBDA(
                // the main object needs to be first in the array [0] with attached objects following
-               float slot, physics, solidity;
-               if(head == e) // this is the main object, place it first
+               int slot, physics, solidity;
+               if(it == e) // this is the main object, place it first
                {
                        slot = 0;
-                       solidity = head.solid; // applied solidity is normal solidity for children
-                       physics = head.move_movetype; // applied physics are normal physics for parents
+                       solidity = it.solid; // applied solidity is normal solidity for children
+                       physics = it.move_movetype; // applied physics are normal physics for parents
                }
-               else if(head.owner == e) // child object, list them in order
+               else if(it.owner == e) // child object, list them in order
                {
-                       i += 1; // children start from 1
-                       slot = i;
-                       solidity = head.old_solid; // persisted solidity is normal solidity for children
-                       physics = head.old_movetype; // persisted physics are normal physics for children
-                       gettaginfo(head.owner, head.tag_index); // get the name of the tag our object is attached to, used further below
+                       o += 1; // children start from 1
+                       slot = o;
+                       solidity = it.old_solid; // persisted solidity is normal solidity for children
+                       physics = it.old_movetype; // persisted physics are normal physics for children
+                       gettaginfo(it.owner, it.tag_index); // get the name of the tag our object is attached to, used further below
                }
                else
                        continue;
@@ -258,46 +254,55 @@ string sandbox_ObjectPort_Save(entity e, float database)
                if(slot)
                {
                        // properties stored only for child objects
-                       if(gettaginfo_name)     port_string[slot] = strcat(port_string[slot], "\"", gettaginfo_name, "\" ");    else    port_string[slot] = strcat(port_string[slot], "\"\" "); // none
+                       if(gettaginfo_name)
+                               port_string[slot] = strcat(port_string[slot], "\"", gettaginfo_name, "\" ");
+                       else
+                               port_string[slot] = strcat(port_string[slot], "\"\" "); // none
                }
                else
                {
                        // properties stored only for parent objects
                        if(database)
                        {
-                               port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", head.origin), " ");
-                               port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", head.angles), " ");
+                               port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", it.origin), " ");
+                               port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", it.angles), " ");
                        }
                }
                // properties stored for all objects
-               port_string[slot] = strcat(port_string[slot], "\"", head.model, "\" ");
-               port_string[slot] = strcat(port_string[slot], ftos(head.skin), " ");
-               port_string[slot] = strcat(port_string[slot], ftos(head.alpha), " ");
-               port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", head.colormod), " ");
-               port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", head.glowmod), " ");
-               port_string[slot] = strcat(port_string[slot], ftos(head.frame), " ");
-               port_string[slot] = strcat(port_string[slot], ftos(head.scale), " ");
+               port_string[slot] = strcat(port_string[slot], "\"", it.model, "\" ");
+               port_string[slot] = strcat(port_string[slot], ftos(it.skin), " ");
+               port_string[slot] = strcat(port_string[slot], ftos(it.alpha), " ");
+               port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", it.colormod), " ");
+               port_string[slot] = strcat(port_string[slot], sprintf("\"%.9v\"", it.glowmod), " ");
+               port_string[slot] = strcat(port_string[slot], ftos(it.frame), " ");
+               port_string[slot] = strcat(port_string[slot], ftos(it.scale), " ");
                port_string[slot] = strcat(port_string[slot], ftos(solidity), " ");
                port_string[slot] = strcat(port_string[slot], ftos(physics), " ");
-               port_string[slot] = strcat(port_string[slot], ftos(head.damageforcescale), " ");
-               if(head.material)       port_string[slot] = strcat(port_string[slot], "\"", head.material, "\" ");      else    port_string[slot] = strcat(port_string[slot], "\"\" "); // none
+               port_string[slot] = strcat(port_string[slot], ftos(it.damageforcescale), " ");
+               if(it.material)
+                       port_string[slot] = strcat(port_string[slot], "\"", it.material, "\" ");
+               else
+                       port_string[slot] = strcat(port_string[slot], "\"\" "); // none
                if(database)
                {
                        // properties stored only for the database
-                       if(head.crypto_idfp)    port_string[slot] = strcat(port_string[slot], "\"", head.crypto_idfp, "\" ");   else    port_string[slot] = strcat(port_string[slot], "\"\" "); // none
+                       if(it.crypto_idfp)
+                               port_string[slot] = strcat(port_string[slot], "\"", it.crypto_idfp, "\" ");
+                       else
+                               port_string[slot] = strcat(port_string[slot], "\"\" "); // none
                        port_string[slot] = strcat(port_string[slot], "\"", e.netname, "\" ");
                        port_string[slot] = strcat(port_string[slot], "\"", e.message, "\" ");
                        port_string[slot] = strcat(port_string[slot], "\"", e.message2, "\" ");
                }
-       }
+       ));
 
        // now apply the array to a simple string, with the ; symbol separating objects
-       s = "";
-       for(i = 0; i <= MAX_STORAGE_ATTACHMENTS; ++i)
+       string s = "";
+       for(int j = 0; j <= MAX_STORAGE_ATTACHMENTS; ++j)
        {
-               if(port_string[i])
-                       s = strcat(s, port_string[i], "; ");
-               port_string[i] = string_null; // fully clear the string
+               if(port_string[j])
+                       s = strcat(s, port_string[j], "; ");
+               port_string[j] = string_null; // fully clear the string
        }
 
        return s;
@@ -375,7 +380,6 @@ entity sandbox_ObjectPort_Load(entity this, string s, float database)
 void sandbox_Database_Save()
 {
        // saves all objects to the database file
-       entity head;
        string file_name;
        float file_get;
 
@@ -384,15 +388,11 @@ void sandbox_Database_Save()
        fputs(file_get, strcat("// sandbox storage \"", autocvar_g_sandbox_storage_name, "\" for map \"", GetMapname(), "\" last updated ", strftime(true, "%d-%m-%Y %H:%M:%S")));
        fputs(file_get, strcat(" containing ", ftos(object_count), " objects\n"));
 
-       for(head = NULL; (head = find(head, classname, "object")); )
+       IL_EACH(g_sandbox_objects, !it.owner, // attached objects are persisted separately, ignore them here
        {
-               // attached objects are persisted separately, ignore them here
-               if(head.owner != NULL)
-                       continue;
-
                // use a line of text for each object, listing all properties
-               fputs(file_get, strcat(sandbox_ObjectPort_Save(head, true), "\n"));
-       }
+               fputs(file_get, strcat(sandbox_ObjectPort_Save(it, true), "\n"));
+       });
        fclose(file_get);
 }
 
@@ -784,10 +784,8 @@ MUTATOR_HOOKFUNCTION(sandbox, SV_ParseClientCommand)
                                                        // this should show the same info as 'mesh' but for attachments
                                                        s = "";
                                                        j = 0;
-                                                       FOREACH_ENTITY_ENT(owner, e,
+                                                       IL_EACH(g_sandbox_objects, it.owner == e,
                                                        {
-                                                               if(it.classname != "object") continue;
-
                                                                ++j; // start from 1
                                                                gettaginfo(e, it.tag_index);
                                                                s = strcat(s, "^1attachment ", ftos(j), "^7 has mesh \"^3", it.model, "^7\" at animation frame ^3", ftos(it.frame));
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..f6a0afdf404c1fdb173299f20d86dee76a25e65c 100644 (file)
@@ -1 +1,4 @@
 #pragma once
+
+IntrusiveList g_sandbox_objects;
+STATIC_INIT(g_sandbox_objects) { g_sandbox_objects = IL_NEW(); }
index acd570d0b67aeb7318267717b08ca924e1b7c949..dd5f3a164b58502f1b9bdacab31c4f1789145bbf 100644 (file)
@@ -1532,8 +1532,8 @@ void Kill_Notification(
        net_notif.nent_net_name = ORDINAL(net_cpid);
        Net_LinkEntity(net_notif, false, autocvar_notification_lifetime_runtime, Net_Write_Notification);
 
-       FOREACH_ENTITY_CLASS(
-               "net_notification",
+       IL_EACH(
+               g_notifications,
                (it.owner.nent_type == net_type || net_type == MSG_Null) && (it.owner.nent_cpid == net_cpid || net_cpid == CPID_Null),
                {
                        it.nent_net_name = -1;
@@ -1682,6 +1682,7 @@ void Send_Notification(
        else
        {
                entity net_notif = new_pure(net_notification);
+               IL_PUSH(g_notifications, net_notif);
                net_notif.owner = notif;
                net_notif.nent_broadcast = broadcast;
                net_notif.nent_client = client;
index 2715925944b6d16ae1701c4a3f0b5ba70db7c815..ccdcc690a8148cbc5308221823587225311af3c8 100644 (file)
@@ -225,6 +225,11 @@ string prev_soundfile;
 float prev_soundtime;
 #endif
 
+#ifdef SVQC
+IntrusiveList g_notifications;
+STATIC_INIT(g_notifications) { g_notifications = IL_NEW(); }
+#endif
+
 #ifdef SVQC
 ENUMCLASS(NOTIF)
        /** send to one client and their spectators */
index ebc971141447e77c2a5a72ad18f11e05746b392b..6e4b05a912fba0188765468b494c0b4ab5bffefb 100644 (file)
@@ -835,9 +835,8 @@ LABEL(pickup)
                if(this.team)
                {
                        RandomSelection_Init();
-                       FOREACH_ENTITY_FLAGS(flags, FL_ITEM,
+                       IL_EACH(g_items, it.team == this.team,
                        {
-                               if(it.team == this.team)
                                if(it.classname != "item_flag_team" && it.classname != "item_key_team")
                                {
                                        Item_Show(it, -1);
@@ -880,9 +879,8 @@ void Item_FindTeam(entity this)
                // marker for item team search
                LOG_TRACE("Initializing item team ", ftos(this.team));
                RandomSelection_Init();
-               FOREACH_ENTITY_FLOAT(team, this.team,
+               IL_EACH(g_items, it.team == this.team,
                {
-                       if(it.flags & FL_ITEM)
                        if(it.classname != "item_flag_team" && it.classname != "item_key_team")
                                RandomSelection_Add(it, 0, string_null, it.cnt, 0);
                });
@@ -891,9 +889,8 @@ void Item_FindTeam(entity this)
                e.state = 0;
                Item_Show(e, 1);
 
-               FOREACH_ENTITY_FLOAT(team, this.team,
+               IL_EACH(g_items, it.team == this.team,
                {
-                       if(it.flags & FL_ITEM)
                        if(it.classname != "item_flag_team" && it.classname != "item_key_team")
                        {
                                if(it != e)
@@ -1076,6 +1073,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                this.weapons = WepSet_FromWeapon(Weapons_from(weaponid));
 
        this.flags = FL_ITEM | itemflags;
+       IL_PUSH(g_items, this);
 
        if(MUTATOR_CALLHOOK(FilterItem, this)) // error means we do not want the item
        {
@@ -1447,10 +1445,9 @@ void target_items_use(entity this, entity actor, entity trigger)
                EXACTTRIGGER_TOUCH(this, trigger);
        }
 
-       FOREACH_ENTITY_ENT(enemy, actor,
+       IL_EACH(g_items, it.enemy == actor && it.classname == "droppedweapon",
        {
-               if(it.classname == "droppedweapon")
-                       delete(it);
+               delete(it);
        });
 
        if(GiveItems(actor, 0, tokenize_console(this.netname)))
index 2b7a1155f483b101c8b122a5986df60f8d270219..13094e790aa527db25853d5a7f72944490c2b57b 100644 (file)
@@ -134,6 +134,8 @@ void func_breakable_behave_destroyed(entity this)
 {
        this.health = this.max_health;
        this.takedamage = DAMAGE_NO;
+       if(this.bot_attack)
+               IL_REMOVE(g_bot_targets, this);
        this.bot_attack = false;
        this.event_damage = func_null;
        this.state = 1;
@@ -155,6 +157,8 @@ void func_breakable_behave_restore(entity this)
        if(!(this.spawnflags & 4))
        {
                this.takedamage = DAMAGE_AIM;
+               if(!this.bot_attack)
+                       IL_PUSH(g_bot_targets, this);
                this.bot_attack = true;
                this.event_damage = func_breakable_damage;
        }
@@ -351,7 +355,7 @@ spawnfunc(func_breakable)
        this.reset = func_breakable_reset;
        this.reset(this);
 
-       this.init_for_player_needed = 1;
+       IL_PUSH(g_initforplayer, this);
        this.init_for_player = func_breakable_init_for_player;
 
        CSQCMODEL_AUTOINIT(this);
index 4902deea5c27307dac17b4e673db17a76da8a400..90328da23002dd61a1a8cc37fb9b6c93705fb7d9 100644 (file)
@@ -11,9 +11,10 @@ void conveyor_think(entity this)
 #endif
 
        // set mythis as current conveyor where possible
-       FOREACH_ENTITY_ENT(conveyor, this,
+       IL_EACH(g_conveyed, it.conveyor == this,
        {
                it.conveyor = NULL;
+               IL_REMOVE(g_conveyed, it);
        });
 
        if(this.state)
@@ -29,10 +30,14 @@ void conveyor_think(entity this)
                        }
                        if(boxesoverlap(emin, emax, this.absmin, this.absmax)) // quick
                                if(WarpZoneLib_BoxTouchesBrush(emin, emax, this, it)) // accurate
+                               {
+                                       if(!it.conveyor)
+                                               IL_PUSH(g_conveyed, it);
                                        it.conveyor = this;
+                               }
                });
 
-               FOREACH_ENTITY_ENT(conveyor, this,
+               IL_EACH(g_conveyed, it.conveyor == this,
                {
                        if(IS_CLIENT(it)) // doing it via velocity has quite some advantages
                                continue; // done in SV_PlayerPhysics   continue;
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..c12b52d2dd19118e4d0a7209329796446922cbeb 100644 (file)
@@ -1 +1,4 @@
 #pragma once
+
+IntrusiveList g_conveyed;
+STATIC_INIT(g_conveyed) { g_conveyed = IL_NEW(); }
index efe997c855350d402a9e4a9a0221eb0099e79862..0b8930aec5a494aca16a3a889a5b02fdb2df8bf9 100644 (file)
@@ -20,6 +20,8 @@ void fd_secret_use(entity this, entity actor, entity trigger)
        string message_save;
 
        this.health = 10000;
+       if(!this.bot_attack)
+               IL_PUSH(g_bot_targets, this);
        this.bot_attack = true;
 
        // exit if still moving around...
index c8e3539283d76652c719e3ce0f82c9c5669f441d..0fde9e043904d00f4093fe74bcc45a9ce0a74b52 100644 (file)
@@ -12,6 +12,9 @@ REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_MUSIC)
 
 #ifdef SVQC
 
+IntrusiveList g_targetmusic_list;
+STATIC_INIT(g_targetmusic_list) { g_targetmusic_list = IL_NEW(); }
+
 // values:
 //   volume
 //   noise
@@ -37,7 +40,8 @@ void target_music_reset(entity this)
 }
 void target_music_kill()
 {
-       FOREACH_ENTITY_CLASS("target_music", true, {
+       IL_EACH(g_targetmusic_list, true,
+       {
                it.volume = 0;
         if (it.targetname == "")
             target_music_sendto(it, MSG_ALL, 1);
@@ -65,6 +69,7 @@ spawnfunc(target_music)
        this.reset = target_music_reset;
        if(!this.volume)
                this.volume = 1;
+       IL_PUSH(g_targetmusic_list, this);
        if(this.targetname == "")
                target_music_sendto(this, MSG_INIT, 1);
        else
@@ -72,7 +77,7 @@ spawnfunc(target_music)
 }
 void TargetMusic_RestoreGame()
 {
-       FOREACH_ENTITY_CLASS("target_music", true,
+       IL_EACH(g_targetmusic_list, true,
        {
                if(it.targetname == "")
                        target_music_sendto(it, MSG_INIT, 1);
index a1a38d39e1a95e24459d2a2c4c1a5bb857c7de27..b5e97b1fc7516f1a082a82d69c354a85f4b8594e 100644 (file)
@@ -267,10 +267,10 @@ void teleport_findtarget(entity this)
 
 entity Teleport_Find(vector mi, vector ma)
 {
-       entity e;
-       for(e = NULL; (e = find(e, classname, "trigger_teleport")); )
-               if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, NULL))
-                       return e;
+       IL_EACH(g_teleporters, WarpZoneLib_BoxTouchesBrush(mi, ma, it, NULL),
+       {
+               return it;
+       });
        return NULL;
 }
 
index 513ed3e26928460e636b36940fa0d009c5213241..6f5f8cb76e21bec6f941b85e2aebccd767b5ba21 100644 (file)
@@ -1,5 +1,8 @@
 #pragma once
 
+IntrusiveList g_teleporters;
+STATIC_INIT(g_teleporters) { g_teleporters = IL_NEW(); }
+
 .entity pusher;
 const float TELEPORT_FLAG_SOUND = 1;
 const float TELEPORT_FLAG_PARTICLES = 2;
index 05bb13c710e7ed4c4289f92acbd137c82da3505c..c3de654609ff5e0db36ad1bf01e4b314b3283023 100644 (file)
@@ -99,6 +99,8 @@ spawnfunc(trigger_teleport)
                return;
        }
 
+       IL_PUSH(g_teleporters, this);
+
        this.teleport_next = teleport_first;
        teleport_first = this;
 }
@@ -106,6 +108,8 @@ spawnfunc(trigger_teleport)
 NET_HANDLE(ENT_CLIENT_TRIGGER_TELEPORT, bool isnew)
 {
        this.classname = "trigger_teleport";
+       if(isnew)
+               IL_PUSH(g_teleporters, this);
        int mytm = ReadByte(); if(mytm) { this.team = mytm - 1; }
        this.spawnflags = ReadInt24_t();
        this.active = ReadByte();
index dabb7ee35dfcdbcb8845f4014355be79168ae8de..c90eaff1fe98fdb22bc7918fefedd1f28c703738 100644 (file)
@@ -479,6 +479,7 @@ entity turret_projectile(entity actor, Sound _snd, float _size, float _health, f
        proj.velocity           = normalize(actor.tur_shotdir_updated + randomvec() * actor.shot_spread) * actor.shot_speed;
        proj.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, proj);
+       IL_PUSH(g_bot_dodge, proj);
        proj.enemy                = actor.enemy;
        proj.totalfrags  = _death;
        PROJECTILE_MAKETRIGGER(proj);
@@ -1252,6 +1253,7 @@ bool turret_initialize(entity this, Turret tur)
        if(!this.tur_head) {
                tur.tr_precache(tur);
                IL_PUSH(g_turrets, this);
+               IL_PUSH(g_bot_targets, this);
        }
 
        entity e = find(NULL, classname, "turret_manager");
index f2a97d4a12529e6fd576819d7509b5bd55597937..152a7d6a2715e362fde40fca3be8f20497ccc511 100644 (file)
@@ -5,7 +5,8 @@ void turret_targettrigger_touch(entity this, entity toucher);
 void turret_targettrigger_touch(entity this, entity toucher)
 {
     if (this.cnt > time) return;
-    FOREACH_ENTITY_STRING_ORDERED(targetname, this.target, {
+    IL_EACH(g_turrets, it.targetname == this.target,
+    {
         if (!(it.turret_flags & TUR_FLAG_RECIEVETARGETS)) continue;
         if (!it.turret_addtarget) continue;
         it.turret_addtarget(it, toucher, this);
index 2e08f5eb3d723cedefe9d790dbea66ee1c572f4e..bf901d886a77e407292d8d208d20f37819f5b8cc 100644 (file)
@@ -36,6 +36,7 @@ METHOD(PhaserTurretAttack, wr_think, void(entity thiswep, entity actor, .entity
         set_movetype(beam, MOVETYPE_NONE);
         beam.enemy = actor.enemy;
         beam.bot_dodge = true;
+        IL_PUSH(g_bot_dodge, beam);
         beam.bot_dodgerating = beam.shot_dmg;
         sound (beam, CH_SHOTS_SINGLE, SND_TUR_PHASER, VOL_BASE, ATTEN_NORM);
         actor.fireflag = 1;
index 94ecdd332a0a264625d7ac7be3727564b60bf8c3..ffba71439ab995198c760c69843a7bfbe1b3e3d7 100644 (file)
@@ -241,6 +241,7 @@ void walker_fire_rocket(entity this, vector org)
     settouch(rocket, walker_rocket_touch);
     rocket.flags = FL_PROJECTILE;
     IL_PUSH(g_projectiles, rocket);
+    IL_PUSH(g_bot_dodge, rocket);
     rocket.solid                         = SOLID_BBOX;
     rocket.max_health           = time + 9;
     rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
index 716abaf9880f183d47d9a82cd8c3af52e9b0eeb4..dc60b95c3d7e0787bf475481b03d7b46a8af4213 100644 (file)
@@ -600,7 +600,7 @@ float cvar_settemp(string tmp_cvar, string tmp_value)
                return 0;
        }
 
-       FOREACH_ENTITY_CLASS("saved_cvar_value", it.netname == tmp_cvar,
+       IL_EACH(g_saved_cvars, it.netname == tmp_cvar,
        {
                created_saved_value = -1; // skip creation
                break; // no need to continue
@@ -610,6 +610,7 @@ float cvar_settemp(string tmp_cvar, string tmp_value)
        {
                // creating a new entity to keep track of this cvar
                entity e = new_pure(saved_cvar_value);
+               IL_PUSH(g_saved_cvars, e);
                e.netname = strzone(tmp_cvar);
                e.message = strzone(cvar_string(tmp_cvar));
                created_saved_value = 1;
index 9e1d5a75be3f94cf418fca7aecb9e4459d28aa44..90e2152d0179f17336bf7a7b1a1546fac3948cb5 100644 (file)
@@ -5,6 +5,9 @@
 vector real_origin(entity ent);
 #endif
 
+IntrusiveList g_saved_cvars;
+STATIC_INIT(g_saved_cvars) { g_saved_cvars = IL_NEW(); }
+
 // this returns a tempstring containing a copy of s with additional \n newlines added, it also replaces \n in the text with a real newline
 // NOTE: s IS allowed to be a tempstring
 string wordwrap(string s, float l);
index 39f959d14b9f03f851f6b8edebf6d3efd90008e3..60a8ee07760fbe897e58cd58fab2e22904337728 100644 (file)
@@ -249,6 +249,7 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound,
        set_movetype(proj, MOVETYPE_FLYMISSILE);
        proj.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, proj);
+       IL_PUSH(g_bot_dodge, proj);
        proj.bot_dodge          = true;
        proj.bot_dodgerating  = _dmg;
        proj.velocity            = _vel;
@@ -433,17 +434,15 @@ void vehicles_reset_colors(entity this)
 void vehicles_clearreturn(entity veh)
 {
        // Remove "return helper" entities, if any.
-       FOREACH_ENTITY_ENT(wp00, veh,
+       IL_EACH(g_vehicle_returners, it.wp00 == veh,
        {
-               if(it.classname == "vehicle_return")
-               {
-                       it.classname = "";
-                       setthink(it, SUB_Remove);
-                       it.nextthink = time + 0.1;
+               it.classname = "";
+               setthink(it, SUB_Remove);
+               it.nextthink = time + 0.1;
+               IL_REMOVE(g_vehicle_returners, it);
 
-                       if(it.waypointsprite_attached)
-                               WaypointSprite_Kill(it.waypointsprite_attached);
-               }
+               if(it.waypointsprite_attached)
+                       WaypointSprite_Kill(it.waypointsprite_attached);
        });
 }
 
@@ -513,6 +512,7 @@ void vehicles_setreturn(entity veh)
        vehicles_clearreturn(veh);
 
        entity ret = new(vehicle_return);
+       IL_PUSH(g_vehicle_returners, ret);
        ret.wp00           = veh;
        ret.team                = veh.team;
        setthink(ret, vehicles_showwp);
@@ -1076,6 +1076,8 @@ void vehicles_spawn(entity this)
        this.solid                              = SOLID_SLIDEBOX;
        this.takedamage                 = DAMAGE_AIM;
        this.deadflag                   = DEAD_NO;
+       if(!this.bot_attack)
+               IL_PUSH(g_bot_targets, this);
        this.bot_attack                 = true;
        this.flags                              = FL_NOTARGET;
        this.avelocity                  = '0 0 0';
@@ -1161,6 +1163,7 @@ bool vehicle_initialize(entity this, Vehicle info, bool nodrop)
        this.tur_head.owner                     = this;
        this.takedamage                         = DAMAGE_NO;
        this.bot_attack                         = true;
+       IL_PUSH(g_bot_targets, this);
        this.iscreature                         = true;
        this.teleportable                       = false; // no teleporting for vehicles, too buggy
        this.damagedbycontents          = true;
index 158191f654eed354806d07cf2140d7a6db1176b4..948427db33e0923c8c28af0ddbf61845a2369e32 100644 (file)
@@ -108,4 +108,7 @@ bool vehicle_impulse(entity this, int imp);
 bool vehicles_crushable(entity e);
 float vehicle_altitude(entity this, float amax);
 
+IntrusiveList g_vehicle_returners;
+STATIC_INIT(g_vehicle_returners) { g_vehicle_returners = IL_NEW(); }
+
 #endif
index 502ef80e2cd88af31f94979549c4b6820cb11d0b..4e16efbcc903df3227c1dc30ae419ef7e4f45731 100644 (file)
@@ -201,9 +201,8 @@ void raptor_flare_damage(entity this, entity inflictor, entity attacker, float d
 void raptor_flare_think(entity this)
 {
     this.nextthink = time + 0.1;
-    FOREACH_ENTITY_ENT(enemy, this.owner,
+    IL_EACH(g_projectiles, it.enemy == this.owner,
     {
-        if(it.flags & FL_PROJECTILE)
         if(vdist(this.origin - it.origin, <, autocvar_g_vehicle_raptor_flare_range))
         if(random() > autocvar_g_vehicle_raptor_flare_chase)
             it.enemy = this;
index fc8a4f190b1be8b6feb8a6f6872e4487aebc7dd0..ec06104824e1c555bc7792f0929787344625c1d2 100644 (file)
@@ -314,9 +314,8 @@ void spiderbot_exit(entity this, int eject)
 {
        vector spot;
 
-       FOREACH_ENTITY_ENT(owner, this.owner,
+       IL_EACH(g_projectiles, it.owner == this.owner && it.classname == "spiderbot_rocket",
        {
-               if(it.classname != "spiderbot_rocket") continue;
                it.realowner = this.owner;
                it.owner = NULL;
        });
index dc1f6ba60a29e16190c54d930e285af683b314d0..5f7a2c31c8a928cbbc5efec1d99e869a0c01a6fc 100644 (file)
@@ -48,16 +48,17 @@ void spiderbot_rocket_guided(entity this)
 
 void spiderbot_guide_release(entity this)
 {
-    FOREACH_ENTITY_ENT(realowner, this.owner,
+    bool donetrace = false;
+    IL_EACH(g_projectiles, it.realowner == this.owner && getthink(it) == spiderbot_rocket_guided,
     {
-        if(i == 0) // something exists, let's trace!
-            crosshair_trace(this.owner);
-
-        if(getthink(it) == spiderbot_rocket_guided)
+        if(!donetrace) // something exists, let's trace!
         {
-            it.pos1 = trace_endpos;
-            setthink(it, spiderbot_rocket_unguided);
+            donetrace = true;
+            crosshair_trace(this.owner);
         }
+
+        it.pos1 = trace_endpos;
+        setthink(it, spiderbot_rocket_unguided);
     });
 }
 
index 1f8b8e7f085e7d6e6484095e3cb4a6cb279dcea5..a61dc0f031d3e9ed4da12e1be93b8e69c703b9fc 100644 (file)
@@ -282,6 +282,7 @@ void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
        missile = new(missile);
        missile.owner = missile.realowner = actor;
        missile.bot_dodge = true;
+       IL_PUSH(g_bot_dodge, missile);
        missile.bot_dodgerating = WEP_CVAR(arc, bolt_damage);
 
        missile.takedamage = DAMAGE_YES;
@@ -691,6 +692,7 @@ void W_Arc_Beam(float burst, entity actor, .entity weaponentity)
        beam.owner = actor;
        set_movetype(beam, MOVETYPE_NONE);
        beam.bot_dodge = true;
+       IL_PUSH(g_bot_dodge, beam);
        beam.bot_dodgerating = WEP_CVAR(arc, beam_damage);
        beam.beam_bursting = burst;
        Net_LinkEntity(beam, false, 0, W_Arc_Beam_Send);
index 2f24e9e254bcb495b4c53782f4434771ed1269b8..2eb8f00b4179c72cd91727168bbee9f7719c93d4 100644 (file)
@@ -140,6 +140,7 @@ void W_Blaster_Attack(
        settouch(missile, W_Blaster_Touch);
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
        missile.missile_flags = MIF_SPLASH;
        missile.projectiledeathtype = atk_deathtype;
        setthink(missile, W_Blaster_Think);
index be5b2ec28f2d96c9cfb8a4270315dda36d1e9306..58214bf390feed3d2f41e1ec5ec24c847b02c10f 100644 (file)
@@ -441,6 +441,7 @@ void W_Crylink_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 
                proj.flags = FL_PROJECTILE;
                IL_PUSH(g_projectiles, proj);
+               IL_PUSH(g_bot_dodge, proj);
                proj.missile_flags = MIF_SPLASH;
 
                CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
@@ -557,6 +558,7 @@ void W_Crylink_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 
                proj.flags = FL_PROJECTILE;
                IL_PUSH(g_projectiles, proj);
+               IL_PUSH(g_bot_dodge, proj);
         proj.missile_flags = MIF_SPLASH;
 
                CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
index 5ffe08bad9613ee7303ab9c256d8726e97b13f52..409f0eab69e6ee53eea47178efe69449c6cbf754 100644 (file)
@@ -400,6 +400,7 @@ void W_Devastator_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        missile.cnt = time + WEP_CVAR(devastator, lifetime);
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
        missile.missile_flags = MIF_SPLASH;
 
        CSQCProjectile(missile, WEP_CVAR(devastator, guiderate) == 0 && WEP_CVAR(devastator, speedaccel) == 0, PROJECTILE_ROCKET, false); // because of fly sound
@@ -415,35 +416,6 @@ void W_Devastator_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        MUTATOR_CALLHOOK(EditProjectile, actor, missile);
 }
 
-#if 0
-METHOD(Devastator, wr_aim, void(entity thiswep, entity actor))
-{
-    entity this = actor;
-    // aim and decide to fire if appropriate
-    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false);
-    if(skill >= 2) // skill 0 and 1 bots won't detonate rockets!
-    {
-        // decide whether to detonate rockets
-        entity missile, targetlist, targ;
-        targetlist = findchainfloat(bot_attack, true);
-        for(missile = NULL; (missile = find(missile, classname, "rocket")); ) if(missile.realowner == actor)
-        {
-            targ = targetlist;
-            while(targ)
-            {
-                if(targ != missile.realowner && vlen(targ.origin - missile.origin) < WEP_CVAR(devastator, radius))
-                {
-                    PHYS_INPUT_BUTTON_ATCK2(actor) = true;
-                    break;
-                }
-                targ = targ.chain;
-            }
-        }
-
-        if(PHYS_INPUT_BUTTON_ATCK2(actor)) PHYS_INPUT_BUTTON_ATCK(actor) = false;
-    }
-}
-#else
 METHOD(Devastator, wr_aim, void(entity thiswep, entity actor))
 {
     // aim and decide to fire if appropriate
@@ -460,12 +432,10 @@ METHOD(Devastator, wr_aim, void(entity thiswep, entity actor))
         selfdamage = 0;
         teamdamage = 0;
         enemydamage = 0;
-        FOREACH_ENTITY_ENT(realowner, actor,
+        IL_EACH(g_projectiles, it.realowner == actor && it.classname == "rocket",
         {
-            if(it.classname != "rocket") continue;
-
             entity rocket = it;
-            FOREACH_ENTITY_FLOAT(bot_attack, true,
+            IL_EACH(g_bot_targets, it.bot_attack,
             {
                float d = vlen(it.origin + (it.mins + it.maxs) * 0.5 - rocket.origin);
                d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
@@ -486,14 +456,12 @@ METHOD(Devastator, wr_aim, void(entity thiswep, entity actor))
             desirabledamage = desirabledamage - teamdamage;
 
         makevectors(actor.v_angle);
-        FOREACH_ENTITY_ENT(realowner, actor,
+        IL_EACH(g_projectiles, it.realowner == actor && it.classname == "rocket",
         {
-            if(it.classname != "rocket") continue;
-
             if(skill > 9) // normal players only do this for the target they are tracking
             {
                    entity rocket = it;
-                   FOREACH_ENTITY_FLOAT(bot_attack, true,
+                   IL_EACH(g_bot_targets, it.bot_attack,
                    {
                        if((v_forward * normalize(rocket.origin - it.origin) < 0.1)
                            && desirabledamage > 0.1 * coredamage
@@ -526,7 +494,7 @@ METHOD(Devastator, wr_aim, void(entity thiswep, entity actor))
         if(PHYS_INPUT_BUTTON_ATCK2(actor)) PHYS_INPUT_BUTTON_ATCK(actor) = false;
     }
 }
-#endif
+
 METHOD(Devastator, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
     if(WEP_CVAR(devastator, reload_ammo) && actor.clip_load < WEP_CVAR(devastator, ammo)) { // forced reload
index bd6fb89694bda3bb0d4a265cc3d525c66218822d..7e05241a490873f200bbd1ecbeb5cbd8ec43e0ab 100644 (file)
@@ -301,6 +301,7 @@ void W_Electro_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
        setsize(proj, '0 0 -3', '0 0 -3');
        proj.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, proj);
+       IL_PUSH(g_bot_dodge, proj);
        proj.missile_flags = MIF_SPLASH;
 
        CSQCProjectile(proj, true, PROJECTILE_ELECTRO_BEAM, true);
@@ -340,6 +341,8 @@ void W_Electro_Orb_Stick(entity this, entity to)
        newproj.nextthink = this.nextthink;
        newproj.use = this.use;
        newproj.flags = this.flags;
+       IL_PUSH(g_projectiles, newproj);
+       IL_PUSH(g_bot_dodge, newproj);
 
        delete(this);
 
@@ -448,6 +451,7 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity)
        proj.event_damage = W_Electro_Orb_Damage;
        proj.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, proj);
+       IL_PUSH(g_bot_dodge, proj);
        proj.damagedbycontents = (WEP_CVAR_SEC(electro, damagedbycontents));
 
        proj.bouncefactor = WEP_CVAR_SEC(electro, bouncefactor);
index db87ee445f8b9a379f267017ca4eaa072d7dc5e2..c2b93747c8c4c14d7d9437f6c50e2cc2934b8d89 100644 (file)
@@ -224,6 +224,7 @@ void W_Fireball_Attack1(entity actor, .entity weaponentity)
        setsize(proj, '-16 -16 -16', '16 16 16');
        proj.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, proj);
+       IL_PUSH(g_bot_dodge, proj);
     proj.missile_flags = MIF_SPLASH | MIF_PROXY;
 
        CSQCProjectile(proj, true, PROJECTILE_FIREBALL, true);
@@ -355,6 +356,7 @@ void W_Fireball_Attack2(entity actor, .entity weaponentity)
        proj.angles = vectoangles(proj.velocity);
        proj.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, proj);
+       IL_PUSH(g_bot_dodge, proj);
     proj.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_ARC;
 
        CSQCProjectile(proj, true, PROJECTILE_FIREMINE, true);
index ece4b358950281f125ab71561799b9afb9142e4b..9a178c03bbc0a47dd6fd8af8bdeb8be1ebdd96f4 100644 (file)
@@ -171,6 +171,7 @@ void W_Hagar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        missile.angles = vectoangles(missile.velocity);
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
        missile.missile_flags = MIF_SPLASH;
 
        CSQCProjectile(missile, true, PROJECTILE_HAGAR, true);
@@ -215,6 +216,7 @@ void W_Hagar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        missile.angles = vectoangles(missile.velocity);
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
        missile.missile_flags = MIF_SPLASH;
 
        CSQCProjectile(missile, true, PROJECTILE_HAGAR_BOUNCING, true);
@@ -292,6 +294,7 @@ void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
                missile.angles = vectoangles(missile.velocity);
                missile.flags = FL_PROJECTILE;
                IL_PUSH(g_projectiles, missile);
+               IL_PUSH(g_bot_dodge, missile);
 
                CSQCProjectile(missile, true, PROJECTILE_HAGAR, true);
 
index c77ccc98e4d12377da82b75aff8ffefb1ba46f1c..79bf08193ec05b9b38e3fa1ac1be46ca102043f3 100644 (file)
@@ -112,6 +112,7 @@ void W_HLAC_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
        missile.projectiledeathtype = WEP_HLAC.m_id;
 
        CSQCProjectile(missile, true, PROJECTILE_HLAC, true);
@@ -155,6 +156,7 @@ void W_HLAC_Attack2(entity actor, .entity weaponentity)
 
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
        missile.missile_flags = MIF_SPLASH;
        missile.projectiledeathtype = WEP_HLAC.m_id | HITTYPE_SECONDARY;
 
index b2c317459935f818088d5d9feaa7773232257b3a..23e7c23ae5b2b16ccdd9b918e03ea378cfef60e4 100644 (file)
@@ -181,6 +181,7 @@ void W_Hook_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        gren.angles = '0 0 0';
        gren.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, gren);
+       IL_PUSH(g_bot_dodge, gren);
 
        CSQCProjectile(gren, true, PROJECTILE_HOOKBOMB, true);
 
index a3b356954af68f47a0b07d76ac61aa5d81e4f204..5f5898aa41b78953872242278cfb5e3067a1cf54 100644 (file)
@@ -104,6 +104,7 @@ void W_MineLayer_Stick(entity this, entity to)
        newmine.cnt = this.cnt;
        newmine.flags = this.flags;
        IL_PUSH(g_projectiles, newmine);
+       IL_PUSH(g_bot_dodge, newmine);
 
        delete(this);
 
@@ -373,6 +374,7 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        mine.cnt = (WEP_CVAR(minelayer, lifetime) - WEP_CVAR(minelayer, lifetime_countdown));
        mine.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, mine);
+       IL_PUSH(g_bot_dodge, mine);
        mine.missile_flags = MIF_SPLASH | MIF_ARC | MIF_PROXY;
 
        if(mine.cnt > 0) { mine.cnt += time; }
@@ -436,7 +438,7 @@ METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor))
         IL_EACH(g_mines, it.realowner == actor,
         {
                entity mine = it;
-               FOREACH_ENTITY_FLOAT(bot_attack, true,
+               IL_EACH(g_bot_targets, it.bot_attack,
                {
                        float d = vlen(it.origin + (it.mins + it.maxs) * 0.5 - mine.origin);
                        d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
@@ -463,7 +465,7 @@ METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor))
             if(skill > 9) // normal players only do this for the target they are tracking
             {
                    entity mine = it;
-                   FOREACH_ENTITY_FLOAT(bot_attack, true,
+                   IL_EACH(g_bot_targets, it.bot_attack,
                    {
                        if((v_forward * normalize(mine.origin - it.origin) < 0.1)
                            && desirabledamage > 0.1 * coredamage
index 81be156541cb7f31c40d9dd5081ad76c3b41677d..2206cc57d13bf4dfb2df8791671808d4ee269241 100644 (file)
@@ -248,6 +248,7 @@ void W_Mortar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        gren.angles = vectoangles(gren.velocity);
        gren.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, gren);
+       IL_PUSH(g_bot_dodge, gren);
 
        if(WEP_CVAR_PRI(mortar, type) == 0 || WEP_CVAR_PRI(mortar, type) == 2)
                CSQCProjectile(gren, true, PROJECTILE_GRENADE, true);
@@ -296,6 +297,7 @@ void W_Mortar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        gren.angles = vectoangles(gren.velocity);
        gren.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, gren);
+       IL_PUSH(g_bot_dodge, gren);
 
        if(WEP_CVAR_SEC(mortar, type) == 0 || WEP_CVAR_SEC(mortar, type) == 2)
                CSQCProjectile(gren, true, PROJECTILE_GRENADE, true);
index 8a689e05109086704ecf726a751aafea27463aee..3e4654fcbbcc41171454192188a8e1ef9f72f393 100644 (file)
@@ -90,6 +90,7 @@ void W_Porto_Fail(entity this, float failhard)
                if(move_out_of_solid(this))
                {
                        this.flags = FL_ITEM;
+                       IL_PUSH(g_items, this);
                        this.velocity = trigger_push_calculatevelocity(this.origin, this.realowner, 128);
                        tracetoss(this, this);
                        if(vdist(trace_endpos - this.realowner.origin, <, 128))
@@ -277,6 +278,7 @@ void W_Porto_Attack(entity actor, .entity weaponentity, float type)
        gren.angles = vectoangles(gren.velocity);
        gren.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, gren);
+       IL_PUSH(g_bot_dodge, gren);
 
        gren.portal_id = time;
        actor.porto_current = gren;
index 850659069a30cd71a6c259aa3c4c49775787515a..268e1916edc91d0c9e3468c229946ff6ad7ff166 100644 (file)
@@ -295,6 +295,7 @@ void W_Seeker_Fire_Missile(Weapon thiswep, entity actor, .entity weaponentity, v
        set_movetype(missile, MOVETYPE_FLYMISSILE);
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
        missile.missile_flags = MIF_SPLASH | MIF_GUIDED_TAG;
 
        W_SetupProjVelocity_UP_PRE(missile, seeker, missile_);
@@ -372,6 +373,7 @@ void W_Seeker_Fire_Flac(Weapon thiswep, entity actor, .entity weaponentity)
        missile.projectiledeathtype = WEP_SEEKER.m_id | HITTYPE_SECONDARY;
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
        missile.missile_flags       = MIF_SPLASH;
 
        // csqc projectiles
@@ -594,6 +596,7 @@ void W_Seeker_Fire_Tag(Weapon thiswep, entity actor, .entity weaponentity)
 
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
        //missile.missile_flags = MIF_..?;
 
        set_movetype(missile, MOVETYPE_FLY);
index d9c215e24b9d0ca5541875eee81f3fb99331c5c2..e11e4d8d5211aacc6e6d6e483afd0fe0ac45ea88 100644 (file)
@@ -289,6 +289,7 @@ void W_RocketMinsta_Attack2(entity actor, .entity weaponentity)
         setsize(proj, '0 0 -3', '0 0 -3');
         proj.flags = FL_PROJECTILE;
         IL_PUSH(g_projectiles, proj);
+        IL_PUSH(g_bot_dodge, proj);
         proj.missile_flags = MIF_SPLASH;
 
         CSQCProjectile(proj, true, PROJECTILE_ROCKETMINSTA_LASER, true);
@@ -340,6 +341,7 @@ void W_RocketMinsta_Attack3 (entity actor, .entity weaponentity)
         setsize(proj, '0 0 -3', '0 0 -3');
         proj.flags = FL_PROJECTILE;
         IL_PUSH(g_projectiles, proj);
+        IL_PUSH(g_bot_dodge, proj);
         proj.missile_flags = MIF_SPLASH;
 
         CSQCProjectile(proj, true, PROJECTILE_ROCKETMINSTA_LASER, true);
index 86c15ec473e1bcdee8ad4a29891b5f8462ea9194..30ab014ec988f1a2fae062bbe36115b003257872 100644 (file)
@@ -98,6 +98,9 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); }
        .int Version;  // deprecated, use SendFlags
        .int SendFlags;
 
+       IntrusiveList g_uncustomizables;
+       STATIC_INIT(g_uncustomizables) { g_uncustomizables = IL_NEW(); }
+
        void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
        {
                if (e.classname == "") e.classname = "net_linked";
@@ -135,11 +138,13 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); }
                setcefc(e, customizer);
                e.uncustomizeentityforclient = uncustomizer;
                e.uncustomizeentityforclient_set = !!uncustomizer;
+               if(uncustomizer)
+                       IL_PUSH(g_uncustomizables, e);
        }
 
        void UncustomizeEntitiesRun()
        {
-               FOREACH_ENTITY_FLOAT(uncustomizeentityforclient_set, true, it.uncustomizeentityforclient(it));
+               IL_EACH(g_uncustomizables, it.uncustomizeentityforclient_set, it.uncustomizeentityforclient(it));
        }
 
        STRING_ITERATOR(g_buf, string_null, 0);
index 59af78cb086c2181d662cf68c060a2cced87b5c3..64957b92e09c0b7ea7b26e8955cebcc3e784a60f 100644 (file)
@@ -63,7 +63,6 @@ void bot_think(entity this);
 entity find_bot_by_name(string name);
 entity find_bot_by_number(float number);
 
-void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius);
 void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius);
 void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius);
 
index 502e2532c6924add3d39208cbf90298d6781f450..ca12d0d651cf53e9caa39a6afa01bd3528a466f8 100644 (file)
@@ -436,7 +436,7 @@ void bot_removefromlargestteam()
        int bestcount = 0;
 
        int bcount = 0;
-       FOREACH_ENTITY_FLOAT(isbot, true,
+       FOREACH_CLIENT(it.isbot,
        {
                ++bcount;
 
@@ -486,7 +486,7 @@ void bot_removenewest()
        entity best = NULL;
        int bcount = 0;
 
-       FOREACH_ENTITY_FLOAT(isbot, true,
+       FOREACH_CLIENT(it.isbot,
        {
                ++bcount;
 
index d23c29675a70fa7bc5d2944922f143ee6a7c9a28..45051b6c270f1e738aa05786b3fbc9f54f1ecc34 100644 (file)
@@ -13,6 +13,7 @@
 #include <common/state.qh>
 #include <common/items/_mod.qh>
 
+#include <common/triggers/teleporters.qh>
 #include <common/triggers/trigger/jumppads.qh>
 
 #include <lib/warpzone/common.qh>
@@ -836,6 +837,26 @@ void havocbot_movetogoal(entity this)
        if (((dodge * v_up) < 0) && random()*frametime >= 0.5*bound(0,(10-skill-this.bot_dodgeskill)*0.1,1)) this.havocbot_ducktime=time+0.3/bound(0.1,skill+this.bot_dodgeskill,10);
 }
 
+entity havocbot_gettarget(entity this, bool secondary)
+{
+       entity best = NULL;
+       vector eye = CENTER_OR_VIEWOFS(this);
+       IL_EACH(g_bot_targets, boolean((secondary) ? it.classname == "misc_breakablemodel" : it.classname != "misc_breakablemodel"),
+       {
+               vector v = CENTER_OR_VIEWOFS(it);
+               if(vdist(v - eye, <, autocvar_bot_ai_enemydetectionradius))
+               if(!best || vlen2(CENTER_OR_VIEWOFS(best) - eye) > vlen2(v - eye))
+               if(bot_shouldattack(this, it))
+               {
+                       traceline(eye, v, true, this);
+                       if (trace_ent == it || trace_fraction >= 1)
+                               best = it;
+               }
+       });
+
+       return best;
+}
+
 void havocbot_chooseenemy(entity this)
 {
        entity head, best, head2;
@@ -1214,7 +1235,7 @@ float havocbot_moveto(entity this, vector pos)
        this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_LINKING;
 
        // if pos is inside a teleport, then let's mark it as teleport waypoint
-       FOREACH_ENTITY_CLASS("trigger_teleport", WarpZoneLib_BoxTouchesBrush(pos, pos, it, NULL),
+       IL_EACH(g_teleporters, WarpZoneLib_BoxTouchesBrush(pos, pos, it, NULL),
        {
                wp.wpflags |= WAYPOINTFLAG_TELEPORT;
                this.lastteleporttime = 0;
index 771ab282ddd49039f36fcfbed52a8cb24ccb18c1..dcf18ef19b1f3622a1eb12590ec66d937d51add9 100644 (file)
@@ -19,7 +19,7 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float
        vector o;
        ratingscale = ratingscale * 0.0001; // items are rated around 10000 already
 
-       FOREACH_ENTITY_FLOAT(bot_pickup, true,
+       IL_EACH(g_items, it.bot_pickup,
        {
                o = (it.absmin + it.absmax) * 0.5;
                friend_distance = 10000; enemy_distance = 10000;
@@ -118,19 +118,6 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float
        });
 }
 
-void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius)
-{
-       FOREACH_ENTITY_CLASS("dom_controlpoint", vdist((((it.absmin + it.absmax) * 0.5) - org), <, sradius),
-       {
-               if(it.cnt > -1) // this is just being fought
-                       navigation_routerating(this, it, ratingscale, 5000);
-               else if(it.goalentity.cnt == 0) // unclaimed
-                       navigation_routerating(this, it, ratingscale * 0.5, 5000);
-               else if(it.goalentity.team != this.team) // other team's point
-                       navigation_routerating(this, it, ratingscale * 0.2, 5000);
-       });
-}
-
 void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius)
 {
        if (autocvar_bot_nofire)
index 5b1f2b530de231e60d79dd03f76ea8d758e66809..6f70f09beec2219624baeca92e2cd7deaa104fb4 100644 (file)
@@ -1,2 +1 @@
 #pragma once
-void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius);
index 51325f4f966c10349070f2ac7b9bbb898eb2dc8c..0c563d1ff9e2f1953775caa14b437171fe74c480 100644 (file)
@@ -1000,7 +1000,7 @@ void botframe_updatedangerousobjects(float maxupdate)
                danger = 0;
                m1 = it.mins;
                m2 = it.maxs;
-               FOREACH_ENTITY_FLOAT(bot_dodge, true,
+               IL_EACH(g_bot_dodge, it.bot_dodge,
                {
                        v = it.origin;
                        v.x = bound(m1_x, v.x, m2_x);
index e111b2ab4f043f5174b270b5090f6190a3dfb5c1..fa273410ea6882bd012daff70dffe93c67c17743 100644 (file)
@@ -230,17 +230,10 @@ void bot_commands_init()
 // Returns first bot with matching name
 entity find_bot_by_name(string name)
 {
-       entity bot;
-
-       bot = findchainflags(flags, FL_CLIENT);
-       while (bot)
+       FOREACH_CLIENT(IS_BOT_CLIENT(it) && it.netname == name,
        {
-               if(IS_BOT_CLIENT(bot))
-               if(bot.netname==name)
-                       return bot;
-
-               bot = bot.chain;
-       }
+               return it;
+       });
 
        return NULL;
 }
index 8475640ac7086462ab73f087d6b8fc9603f285c5..efcd5ba3731243acd0260c36d43c0e451d856829 100644 (file)
@@ -1012,7 +1012,7 @@ void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld)
 
 void botframe_deleteuselesswaypoints()
 {
-       FOREACH_ENTITY_FLOAT(bot_pickup, true,
+       IL_EACH(g_items, it.bot_pickup,
        {
                // NOTE: this protects waypoints if they're the ONLY nearest
                // waypoint. That's the intention.
index 271252dee96b47c028839ce4967289e97372e690..b4102cb6c09a20178f8549f1051da6afa71f5f45 100644 (file)
@@ -18,7 +18,6 @@ void bot_think(entity this) { }
 entity find_bot_by_name(string name) { return NULL; }
 entity find_bot_by_number(float number) { return NULL; }
 
-void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius) { }
 void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius) { }
 void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius) { }
 
index 71e0cd2e861805db6342b4203e39066b85ac39bc..185fe8fb4e0f3cf44f473f1c3526714995900a2b 100644 (file)
@@ -913,7 +913,7 @@ void Drag_Finish(entity dragger)
                        break;
        }
 
-       if((draggee.flags & FL_ITEM) && (vlen(draggee.velocity) < 32))
+       if((draggee.flags & FL_ITEM) && (vdist(draggee.velocity, <, 32)))
        {
                draggee.velocity = '0 0 0';
                SET_ONGROUND(draggee); // floating items are FUN
index ed2faee72dd7ed73e1ef21998c2703efc204f209..f71afe7f3bde07892f28e0de9e8fa3b17f536aee 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <common/effects/qc/globalsound.qh>
 
+#include "../common/triggers/func/conveyor.qh"
 #include "../common/triggers/teleporters.qh"
 
 #include "../common/vehicles/all.qh"
@@ -295,6 +296,8 @@ void PutObserverInServer(entity this)
        accuracy_resend(this);
 
        this.spectatortime = time;
+       if(this.bot_attack)
+               IL_REMOVE(g_bot_targets, this);
        this.bot_attack = false;
     this.hud = HUD_NORMAL;
        TRANSMUTE(Observer, this);
@@ -631,11 +634,15 @@ void PutClientInServer(entity this)
                this.oldorigin = this.origin;
                this.prevorigin = this.origin;
                this.lastteleporttime = time; // prevent insane speeds due to changing origin
+               if(this.conveyor)
+                       IL_REMOVE(g_conveyed, this);
                this.conveyor = NULL; // prevent conveyors at the previous location from moving a freshly spawned player
                this.hud = HUD_NORMAL;
 
                this.event_damage = PlayerDamage;
 
+               if(!this.bot_attack)
+                       IL_PUSH(g_bot_targets, this);
                this.bot_attack = true;
                this.monster_attack = true;
 
@@ -938,10 +945,8 @@ void ClientKill_TeamChange (entity this, float targetteam) // 0 = don't change,
                        this.killindicator.count = bound(0, ceil(killtime), 10);
                        //sprint(this, strcat("^1You'll be dead in ", ftos(this.killindicator.cnt), " seconds\n"));
 
-                       FOREACH_ENTITY_ENT(enemy, this,
+                       IL_EACH(g_clones, it.enemy == this && !(it.effects & CSQCMODEL_EF_RESPAWNGHOST),
                        {
-                               if(it.classname != "body")
-                                       continue;
                                it.killindicator = spawn();
                                it.killindicator.owner = it;
                                it.killindicator.scale = 0.5;
@@ -1200,7 +1205,7 @@ void ClientConnect(entity this)
        if (IS_REAL_CLIENT(this))
                sv_notice_join(this);
 
-       FOREACH_ENTITY_FLOAT(init_for_player_needed, true, {
+       IL_EACH(g_initforplayer, it.init_for_player, {
                it.init_for_player(it, this);
        });
 
index 35ff6e961c61808a8f5f3cdd0f87e288653bd4f5..c2317aff0280b46179c7bc52d3d79f95913eba7f 100644 (file)
@@ -2,6 +2,9 @@
 
 void ClientState_attach(entity this);
 
+IntrusiveList g_players;
+STATIC_INIT(g_players) { g_players = IL_NEW(); }
+
 CLASS(Client, Object)
     /** Client name */
     ATTRIB(Client, netname, string, this.netname);
@@ -71,8 +74,11 @@ ENDCLASS(Spectator)
 CLASS(Player, Client)
     INIT(Player) {
         this.classname = STR_PLAYER;
+        IL_PUSH(g_players, this);
+    }
+    DESTRUCTOR(Player) {
+        IL_REMOVE(g_players, this);
     }
-    DESTRUCTOR(Player) { }
 ENDCLASS(Player)
 
 METHOD(Client, m_unwind, bool(Client this))
index a6bd1552d2250d7c0a2ee1895173586b4f9ab81f..b034968901e741e40d348952fdf7ef40ab16f9d9 100644 (file)
@@ -426,7 +426,6 @@ const int MIF_GUIDED_CONFUSABLE = MIF_GUIDED_HEAT | MIF_GUIDED_AI;
 
 .string cvar_cl_physics;
 
-.bool init_for_player_needed;
 .void(entity this, entity player) init_for_player;
 
 IntrusiveList g_monsters;
@@ -446,3 +445,30 @@ STATIC_INIT(g_mines) { g_mines = IL_NEW(); }
 
 IntrusiveList g_projectiles;
 STATIC_INIT(g_projectiles) { g_projectiles = IL_NEW(); }
+
+IntrusiveList g_items;
+STATIC_INIT(g_items) { g_items = IL_NEW(); }
+
+IntrusiveList g_initforplayer;
+STATIC_INIT(g_initforplayer) { g_initforplayer = IL_NEW(); }
+
+IntrusiveList g_clones;
+STATIC_INIT(g_clones) { g_clones = IL_NEW(); }
+
+IntrusiveList g_assault_destructibles;
+STATIC_INIT(g_assault_destructibles) { g_assault_destructibles = IL_NEW(); }
+
+IntrusiveList g_assault_objectivedecreasers;
+STATIC_INIT(g_assault_objectivedecreasers) { g_assault_objectivedecreasers = IL_NEW(); }
+
+IntrusiveList g_assault_objectives;
+STATIC_INIT(g_assault_objectives) { g_assault_objectives = IL_NEW(); }
+
+IntrusiveList g_spawnpoints;
+STATIC_INIT(g_spawnpoints) { g_spawnpoints = IL_NEW(); }
+
+IntrusiveList g_bot_targets;
+STATIC_INIT(g_bot_targets) { g_bot_targets = IL_NEW(); }
+
+IntrusiveList g_bot_dodge;
+STATIC_INIT(g_bot_dodge) { g_bot_dodge = IL_NEW(); }
index e3cada6c84b0acc6332325b7cc9f71ddce10797a..97e82b50edf683eb38804743a13913fedf7f984a 100644 (file)
@@ -526,6 +526,8 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo
        targ.revive_progress = ((frozen_type == 3) ? 1 : 0);
        targ.health = ((frozen_type == 3) ? targ_maxhealth : 1);
        targ.revive_speed = freeze_time;
+       if(targ.bot_attack)
+               IL_REMOVE(g_bot_targets, targ);
        targ.bot_attack = false;
 
        entity ice = new(ice);
@@ -563,6 +565,8 @@ void Unfreeze (entity targ)
        STAT(FROZEN, targ) = 0;
        targ.revive_progress = 0;
        targ.revival_time = time;
+       if(!targ.bot_attack)
+               IL_PUSH(g_bot_targets, targ);
        targ.bot_attack = true;
 
        WaypointSprite_Kill(targ.waypointsprite_attached);
index 46508a9191162f34554428248f7d6118a221d41f..90266189b83c1adf5f4ea6f7db111c9780e3c24c 100644 (file)
@@ -371,6 +371,7 @@ void FireGrapplingHook(entity actor)
        missile.classname = "grapplinghook";
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
+       IL_PUSH(g_bot_dodge, missile);
 
        set_movetype(missile, ((autocvar_g_balance_grapplehook_gravity) ? MOVETYPE_TOSS : MOVETYPE_FLY));
        PROJECTILE_MAKETRIGGER(missile);
index 0f18ad06e85cef6452e3c8eb9bcbc748f7754a36..89e205c2b13506942f87d62a6c9c889d66d7d541 100644 (file)
@@ -555,6 +555,8 @@ spawnfunc(__init_dedicated_server)
        static_init_late();
        static_init_precache();
 
+       IL_PUSH(g_spawnpoints, e); // just incase
+
        MapInfo_Enumerate();
        MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
 }
@@ -1768,7 +1770,8 @@ float WinningCondition_RanOutOfSpawns()
                }
        ));
 
-       FOREACH_ENTITY_CLASS("info_player_deathmatch", true, LAMBDA(
+       IL_EACH(g_spawnpoints, true,
+       {
                switch(it.team)
                {
                        case NUM_TEAM_1: team1_score = 1; break;
@@ -1776,7 +1779,7 @@ float WinningCondition_RanOutOfSpawns()
                        case NUM_TEAM_3: team3_score = 1; break;
                        case NUM_TEAM_4: team4_score = 1; break;
                }
-       ));
+       });
 
        ClearWinners();
        if(team1_score + team2_score + team3_score + team4_score == 0)
index 4660a433ba543fee479e6c053a4d629d3a926ad5..8a10a6d7525f5c973367b7adef18c16546cfd8a6 100644 (file)
@@ -551,7 +551,7 @@ IMPULSE(navwaypoint_unreachable)
        if (m) LOG_INFOF("%d waypoints have been marked total\n", m);
 
        j = 0;
-       FOREACH_ENTITY_CLASS("info_player_deathmatch", true,
+       IL_EACH(g_spawnpoints, true,
        {
                vector org = it.origin;
                tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - '0 0 512', MOVE_NOMONSTERS, NULL);
@@ -578,12 +578,12 @@ IMPULSE(navwaypoint_unreachable)
        if (j) LOG_INFOF("%d spawnpoints have no nearest waypoint (marked by player model)\n", j);
 
        j = 0;
-       FOREACH_ENTITY_FLAGS(flags, FL_ITEM,
+       IL_EACH(g_items, true,
        {
                it.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE);
                it.colormod = '0.5 0.5 0.5';
        });
-       FOREACH_ENTITY_FLAGS(flags, FL_ITEM,
+       IL_EACH(g_items, true,
        {
                if (navigation_findnearestwaypoint(it, false)) continue;
                LOG_INFO("item without waypoint: ", etos(it), " ", vtos(it.origin), "\n");
@@ -594,7 +594,7 @@ IMPULSE(navwaypoint_unreachable)
        if (j) LOG_INFOF("%d items have no nearest waypoint and cannot be walked away from (marked with red light)\n", j);
 
        j = 0;
-       FOREACH_ENTITY_FLAGS(flags, FL_ITEM,
+       IL_EACH(g_items, true,
        {
                if (navigation_findnearestwaypoint(it, true)) continue;
                LOG_INFO("item without waypoint: ", etos(it), " ", vtos(it.origin), "\n");
index 58cd949297acefe1af5e3e48d65f8f098f6c58b4..4b3d404bf316907a579f6d246330d9f591b257c8 100644 (file)
@@ -1144,7 +1144,6 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma
 {
     float m, i;
     vector start, org, delta, end, enddown, mstart;
-    entity sp;
 
     m = e.dphitcontentsmask;
     e.dphitcontentsmask = goodcontents | badcontents;
@@ -1200,16 +1199,26 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma
             continue;
 
        // rule 4: we must "see" some spawnpoint or item
-       for(sp = NULL; (sp = find(sp, classname, "info_player_deathmatch")); )
-               if(checkpvs(mstart, sp))
-                       if((traceline(mstart, sp.origin, MOVE_NORMAL, e), trace_fraction) >= 1)
-                               break;
+    entity sp = NULL;
+    IL_EACH(g_spawnpoints, checkpvs(mstart, it),
+    {
+       if((traceline(mstart, it.origin, MOVE_NORMAL, e), trace_fraction) >= 1)
+       {
+               sp = it;
+               break;
+       }
+    });
        if(!sp)
        {
-               for(sp = NULL; (sp = findflags(sp, flags, FL_ITEM)); )
-                       if(checkpvs(mstart, sp))
-                               if((traceline(mstart, sp.origin + (sp.mins + sp.maxs) * 0.5, MOVE_NORMAL, e), trace_fraction) >= 1)
-                                       break;
+               IL_EACH(g_items, checkpvs(mstart, it),
+               {
+                       if((traceline(mstart, it.origin + (it.mins + it.maxs) * 0.5, MOVE_NORMAL, e), trace_fraction) >= 1)
+                       {
+                               sp = it;
+                               break;
+                       }
+               });
+
                if(!sp)
                        continue;
        }
index 5814e7cb744e2c56ea3a6b257fa2adc76410c117..f4566a9ca667b305a759e05fcf96edf9dc7c6e4c 100644 (file)
@@ -10,13 +10,10 @@ void assault_objective_use(entity this, entity actor, entity trigger)
        //print("^2Activated objective ", this.targetname, "=", etos(this), "\n");
        //print("Activator is ", actor.classname, "\n");
 
-       for (entity e = NULL; (e = find(e, target, this.targetname)); )
+       IL_EACH(g_assault_objectivedecreasers, it.target == this.targetname,
        {
-               if (e.classname == "target_objective_decrease")
-               {
-                       target_objective_decrease_activate(e);
-               }
-       }
+               target_objective_decrease_activate(it);
+       });
 }
 
 vector target_objective_spawn_evalfunc(entity this, entity player, entity spot, vector current)
@@ -74,16 +71,13 @@ void assault_objective_decrease_use(entity this, entity actor, entity trigger)
 
 void assault_setenemytoobjective(entity this)
 {
-       FOREACH_ENTITY_STRING(targetname, this.target,
+       IL_EACH(g_assault_objectives, it.targetname == this.target,
        {
-               if(it.classname == "target_objective")
-               {
-                       if(this.enemy == NULL)
-                               this.enemy = it;
-                       else
-                               objerror(this, "more than one objective as target - fix the map!");
-                       break;
-               }
+               if(this.enemy == NULL)
+                       this.enemy = it;
+               else
+                       objerror(this, "more than one objective as target - fix the map!");
+               break;
        });
 
        if(this.enemy == NULL)
@@ -150,7 +144,8 @@ void assault_roundstart_use(entity this, entity actor, entity trigger)
        SUB_UseTargets(this, this, trigger);
 
        //(Re)spawn all turrets
-       FOREACH_ENTITY_CLASS("turret_main", true, LAMBDA(
+       IL_EACH(g_turrets, true,
+       {
                // Swap turret teams
                if(it.team == NUM_TEAM_1)
                        it.team = NUM_TEAM_2;
@@ -159,7 +154,7 @@ void assault_roundstart_use(entity this, entity actor, entity trigger)
 
                // Doubles as teamchange
                turret_respawn(it);
-       ));
+       });
 }
 void assault_roundstart_use_this(entity this)
 {
@@ -286,6 +281,7 @@ spawnfunc(target_objective)
        if (!g_assault) { delete(this); return; }
 
        this.classname = "target_objective";
+       IL_PUSH(g_assault_objectives, this);
        this.use = assault_objective_use;
        this.reset = assault_objective_reset;
        this.reset(this);
@@ -297,6 +293,7 @@ spawnfunc(target_objective_decrease)
        if (!g_assault) { delete(this); return; }
 
        this.classname = "target_objective_decrease";
+       IL_PUSH(g_assault_objectivedecreasers, this);
 
        if(!this.dmg)
                this.dmg = 101;
@@ -317,6 +314,7 @@ spawnfunc(func_assault_destructible)
 
        this.spawnflags = 3;
        this.classname = "func_assault_destructible";
+       IL_PUSH(g_assault_destructibles, this);
 
        if(assault_attacker_team == NUM_TEAM_1)
                this.team = NUM_TEAM_2;
@@ -364,17 +362,15 @@ spawnfunc(target_assault_roundstart)
 // legacy bot code
 void havocbot_goalrating_ast_targets(entity this, float ratingscale)
 {
-       FOREACH_ENTITY_CLASS("func_assault_destructible", it.bot_attack,
+       IL_EACH(g_assault_destructibles, it.bot_attack,
        {
                if (it.target == "")
                        continue;
 
                bool found = false;
-               FOREACH_ENTITY_STRING(targetname, it.target,
+               entity destr = it;
+               IL_EACH(g_assault_objectivedecreasers, it.targetname == destr.target,
                {
-                       if(it.classname != "target_objective_decrease")
-                               continue;
-
                        if(it.enemy.health > 0 && it.enemy.health < ASSAULT_VALUE_INACTIVE)
                        {
                                found = true;
index 017fb265b9adc89fcb7aa5d63ab61d8c66e8dff6..79ac9994625de1b4a1f05da3ad540dee3d75d876 100644 (file)
@@ -1234,6 +1234,7 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
        flag.classname = "item_flag_team";
        flag.target = "###item###"; // wut?
        flag.flags = FL_ITEM | FL_NOTARGET;
+       IL_PUSH(g_items, flag);
        flag.solid = SOLID_TRIGGER;
        flag.takedamage = DAMAGE_NO;
        flag.damageforcescale = autocvar_g_ctf_flag_damageforcescale;
@@ -1527,7 +1528,7 @@ void havocbot_goalrating_ctf_droppedflags(entity this, float ratingscale, vector
 
 void havocbot_goalrating_ctf_carrieritems(entity this, float ratingscale, vector org, float sradius)
 {
-       FOREACH_ENTITY_FLOAT(bot_pickup, true,
+       IL_EACH(g_items, it.bot_pickup,
        {
                // gather health and armor only
                if (it.solid)
index 33030f2f9cce0057f094d1b173f6959f63f74ffe..4cd8e8767e5f163b58efd886f7e320c8dd66cd71 100644 (file)
@@ -18,7 +18,7 @@ void havocbot_role_cts(entity this)
                this.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
                navigation_goalrating_start(this);
 
-               FOREACH_ENTITY_CLASS("trigger_race_checkpoint", true,
+               IL_EACH(g_racecheckpoints, true,
                {
                        if(it.cnt == this.race_checkpoint)
                                navigation_routerating(this, it, 1000000, 5000);
index 6ad5d4849910f19f468c193dcd4c51707586cb28..abcae5ada5dffb2db2381386b8a9d0a23627d5b4 100644 (file)
@@ -99,7 +99,8 @@ void dompoint_captured(entity this)
        WaypointSprite_UpdateSprites(this.sprite, msg, WP_Null, WP_Null);
 
        total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0;
-       FOREACH_ENTITY_CLASS("dom_controlpoint", true, LAMBDA(
+       IL_EACH(g_dompoints, true,
+       {
                if (autocvar_g_domination_point_amt)
                        points = autocvar_g_domination_point_amt;
                else
@@ -116,7 +117,7 @@ void dompoint_captured(entity this)
                        case NUM_TEAM_4: pps_pink += points/wait_time; break;
                }
                total_pps += points/wait_time;
-       ));
+       });
 
        WaypointSprite_UpdateTeamRadar(this.sprite, RADARICON_DOMPOINT, colormapPaletteColor(this.goalentity.team - 1, 0));
        WaypointSprite_Ping(this.sprite);
@@ -283,6 +284,8 @@ void dom_controlpoint_setup(entity this)
        this.nextthink = time;
        settouch(this, dompointtouch);
        this.solid = SOLID_TRIGGER;
+       if(!this.flags & FL_ITEM)
+               IL_PUSH(g_items, this);
        this.flags = FL_ITEM;
        setsize(this, '-32 -32 -32', '32 32 32');
        setorigin(this, this.origin + '0 0 20');
@@ -296,7 +299,7 @@ float total_controlpoints;
 void Domination_count_controlpoints()
 {
        total_controlpoints = redowned = blueowned = yellowowned = pinkowned = 0;
-       FOREACH_ENTITY_CLASS("dom_controlpoint", true,
+       IL_EACH(g_dompoints, true,
        {
                ++total_controlpoints;
                redowned += (it.goalentity.team == NUM_TEAM_1);
@@ -378,6 +381,19 @@ void Domination_RoundStart()
 }
 
 //go to best items, or control points you don't own
+void havocbot_goalrating_controlpoints(entity this, float ratingscale, vector org, float sradius)
+{
+       IL_EACH(g_dompoints, vdist((((it.absmin + it.absmax) * 0.5) - org), <, sradius),
+       {
+               if(it.cnt > -1) // this is just being fought
+                       navigation_routerating(this, it, ratingscale, 5000);
+               else if(it.goalentity.cnt == 0) // unclaimed
+                       navigation_routerating(this, it, ratingscale * 0.5, 5000);
+               else if(it.goalentity.team != this.team) // other team's point
+                       navigation_routerating(this, it, ratingscale * 0.2, 5000);
+       });
+}
+
 void havocbot_role_dom(entity this)
 {
        if(IS_DEAD(this))
@@ -482,6 +498,8 @@ spawnfunc(dom_controlpoint)
        this.effects = this.effects | EF_LOWPRECISION;
        if (autocvar_g_domination_point_fullbright)
                this.effects |= EF_FULLBRIGHT;
+
+       IL_PUSH(g_dompoints, this);
 }
 
 /*QUAKED spawnfunc_dom_team (0 .5 .8) (-32 -32 -24) (32 32 32)
index e9eb2c2d9da3e4ca46189662785cc13c62f08f2e..609fcfd0d9f01c91afbe25566948f75f96626219 100644 (file)
@@ -61,3 +61,6 @@ float domination_roundbased;
 float domination_teams;
 
 void AnimateDomPoint(entity this);
+
+IntrusiveList g_dompoints;
+STATIC_INIT(g_dompoints) { g_dompoints = IL_NEW(); }
index 1d9dc662017f7743f212588be4a96ba0c8a7f1c4..d43d504821e795aa2c2611107629dbe33416ed8b 100644 (file)
@@ -5,6 +5,8 @@
 
 #include <server/teamplay.qh>
 
+IntrusiveList g_invasion_spawns;
+STATIC_INIT(g_invasion_spawns) { g_invasion_spawns = IL_NEW(); }
 
 float autocvar_g_invasion_round_timelimit;
 float autocvar_g_invasion_spawnpoint_spawn_delay;
@@ -18,6 +20,7 @@ spawnfunc(invasion_spawnpoint)
        if(!g_invasion) { delete(this); return; }
 
        this.classname = "invasion_spawnpoint";
+       IL_PUSH(g_invasion_spawns, this);
 
        if(autocvar_g_invasion_zombies_only) // precache only if it hasn't been already
        if(this.monsterid) {
@@ -52,7 +55,7 @@ entity invasion_PickSpawn()
 {
        RandomSelection_Init();
 
-       FOREACH_ENTITY_CLASS("invasion_spawnpoint", true,
+       IL_EACH(g_invasion_spawns, true,
        {
                RandomSelection_Add(it, 0, string_null, 1, ((time >= it.spawnshieldtime) ? 0.2 : 1)); // give recently used spawnpoints a very low rating
                it.spawnshieldtime = time + autocvar_g_invasion_spawnpoint_spawn_delay;
@@ -340,6 +343,8 @@ MUTATOR_HOOKFUNCTION(inv, PlayerSpawn)
 {
        entity player = M_ARGV(0, entity);
 
+       if(player.bot_attack)
+               IL_REMOVE(g_bot_targets, player);
        player.bot_attack = false;
 }
 
index a430ab5368b0fc92049d5b6e885ad7bee7d5402b..6fa76d6c5c1e140fb15382fffbd15118979f8b23 100644 (file)
@@ -451,6 +451,7 @@ void ka_SpawnBall() // loads various values for the ball, runs only once at star
        e.glow_color = autocvar_g_keepawayball_trail_color;
        e.glow_trail = true;
        e.flags = FL_ITEM;
+       IL_PUSH(g_items, e);
        e.pushable = true;
        e.reset = ka_Reset;
        settouch(e, ka_TouchEvent);
index 86d76e4312c87aff1aa80e8b3602fe020e84b18b..c4e17bf7cc57a611e649a404611eaee952fb9d54 100644 (file)
@@ -283,6 +283,7 @@ void kh_Key_Detach(entity key) // runs every time a key is dropped or lost. Runs
        key.angles_y += key.owner.angles.y;
 #endif
        key.flags = FL_ITEM;
+       IL_PUSH(g_items, key);
        key.solid = SOLID_TRIGGER;
        set_movetype(key, MOVETYPE_TOSS);
        key.pain_finished = time + autocvar_g_balance_keyhunt_delay_return;
index 756d975b156ad197febcbe333455f85d9eaf246f..b791a69dce9830cc42b45743501dce63bbc80ff1 100644 (file)
@@ -14,23 +14,22 @@ void havocbot_role_race(entity this)
        if(IS_DEAD(this))
                return;
 
-       entity e;
        if (this.bot_strategytime < time)
        {
                this.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
                navigation_goalrating_start(this);
 
-               for(e = NULL; (e = find(e, classname, "trigger_race_checkpoint")) != NULL; )
+               IL_EACH(g_racecheckpoints, true,
                {
-                       if(e.cnt == this.race_checkpoint)
+                       if(it.cnt == this.race_checkpoint)
                        {
-                               navigation_routerating(this, e, 1000000, 5000);
+                               navigation_routerating(this, it, 1000000, 5000);
                        }
                        else if(this.race_checkpoint == -1)
                        {
-                               navigation_routerating(this, e, 1000000, 5000);
+                               navigation_routerating(this, it, 1000000, 5000);
                        }
-               }
+               });
 
                navigation_goalrating_end(this);
        }
index f2ceecf9ee4596d1cc9125da2dc7513f69f13c25..e95ae98193281c9ea5a6b1226d22b7a52548b4db 100644 (file)
@@ -126,6 +126,8 @@ void CopyBody(entity this, float keepvelocity)
        animdecide_load_if_needed(clone);
        animdecide_setframes(clone, false, frame, frame1time, frame2, frame2time);
 
+       IL_PUSH(g_clones, clone);
+
        MUTATOR_CALLHOOK(CopyBody, this, clone, keepvelocity);
 }
 
index fc5ba4d61b6dc50866360fb4e3a6cadb05cfe35e..8fc38aa2c5e028ed1d44f8cd5f3b7128454ddda9 100644 (file)
@@ -832,15 +832,14 @@ void trigger_race_checkpoint_verify(entity this)
                                race_timed_checkpoint = 255;
                        }
                } else {
-                       for (entity cp = NULL; (cp = find(cp, classname, "trigger_race_checkpoint")); ) {
-                               if (cp.sprite) {
-                                       if (cp.race_checkpoint == 0) {
-                                               WaypointSprite_UpdateSprites(cp.sprite, WP_RaceStart, WP_Null, WP_Null);
-                    } else if (cp.race_checkpoint == race_timed_checkpoint) {
-                                               WaypointSprite_UpdateSprites(cp.sprite, WP_RaceFinish, WP_Null, WP_Null);
-                    }
+                       IL_EACH(g_racecheckpoints, it.sprite,
+                       {
+                               if (it.race_checkpoint == 0) {
+                                       WaypointSprite_UpdateSprites(it.sprite, WP_RaceStart, WP_Null, WP_Null);
+                } else if (it.race_checkpoint == race_timed_checkpoint) {
+                                       WaypointSprite_UpdateSprites(it.sprite, WP_RaceFinish, WP_Null, WP_Null);
                                }
-            }
+            });
                }
        }
 
@@ -946,6 +945,8 @@ spawnfunc(trigger_race_checkpoint)
        this.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player;
        this.spawn_evalfunc = trigger_race_checkpoint_spawn_evalfunc;
 
+       IL_PUSH(g_racecheckpoints, this);
+
        InitializeEntity(this, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET);
 }
 
@@ -1142,7 +1143,7 @@ float race_GetFractionalLapCount(entity e)
 
        vector o0, o1;
        float bestfraction, fraction;
-       entity lastcp, cp0, cp1;
+       entity lastcp;
        float nextcpindex, lastcpindex;
 
        nextcpindex = max(e.race_checkpoint, 0);
@@ -1153,26 +1154,26 @@ float race_GetFractionalLapCount(entity e)
                return l; // finish
 
        bestfraction = 1;
-       for(cp0 = NULL; (cp0 = find(cp0, classname, "trigger_race_checkpoint")); )
+       IL_EACH(g_racecheckpoints, true,
        {
-               if(cp0.race_checkpoint != lastcpindex)
+               if(it.race_checkpoint != lastcpindex)
                        continue;
                if(lastcp)
-                       if(cp0 != lastcp)
+                       if(it != lastcp)
                                continue;
-               o0 = (cp0.absmin + cp0.absmax) * 0.5;
-               for(cp1 = NULL; (cp1 = find(cp1, classname, "trigger_race_checkpoint")); )
+               o0 = (it.absmin + it.absmax) * 0.5;
+               IL_EACH(g_racecheckpoints, true,
                {
-                       if(cp1.race_checkpoint != nextcpindex)
+                       if(it.race_checkpoint != nextcpindex)
                                continue;
-                       o1 = (cp1.absmin + cp1.absmax) * 0.5;
+                       o1 = (it.absmin + it.absmax) * 0.5;
                        if(o0 == o1)
                                continue;
                        fraction = bound(0.0001, vlen(e.origin - o1) / vlen(o0 - o1), 1);
                        if(fraction < bestfraction)
                                bestfraction = fraction;
-               }
-       }
+               });
+       });
 
        // we are at CP "nextcpindex - bestfraction"
        // race_timed_checkpoint == 4: then nextcp==4 means 0.9999x, nextcp==0 means 0.0000x
index 6360b0ae5aba535b3727c36110ac5a85e099cce1..6419afb737690604dace62c681cabe9da377f4e7 100644 (file)
@@ -29,6 +29,9 @@ float race_completing;
 .float race_respawn_checkpoint;
 .entity race_respawn_spotref; // try THIS spawn in case you respawn
 
+IntrusiveList g_racecheckpoints;
+STATIC_INIT(g_racecheckpoints) { g_racecheckpoints = IL_NEW(); }
+
 // definitions for functions used outside race.qc
 float race_PreviousCheckpoint(float f);
 float race_NextCheckpoint(float f);
index 567217933fb27f5e519326444d21eb14d7a8f864..f4dfe0432022927095c423f578b4599e58bfe27d 100644 (file)
@@ -166,6 +166,7 @@ spawnfunc(info_player_start)
 spawnfunc(info_player_deathmatch)
 {
        this.classname = "info_player_deathmatch";
+       IL_PUSH(g_spawnpoints, this);
        relocate_spawnpoint(this);
 }
 
index 1bb6974eb03ccf0460c46210dda635f8ec45a34f..ea11ea36a613f25ffb8c3f9915c8fa3dbf9c58f0 100644 (file)
@@ -159,8 +159,8 @@ void sys_phys_update(entity this, float dt);
 void StartFrame()
 {
     // TODO: if move is more than 50ms, split it into two moves (this matches QWSV behavior and the client prediction)
-    FOREACH_ENTITY_CLASS(STR_PLAYER, IS_FAKE_CLIENT(it), sys_phys_update(it, frametime));
-    FOREACH_ENTITY_CLASS(STR_PLAYER, IS_FAKE_CLIENT(it), PlayerPreThink(it));
+    IL_EACH(g_players, IS_FAKE_CLIENT(it), sys_phys_update(it, frametime));
+    IL_EACH(g_players, IS_FAKE_CLIENT(it), PlayerPreThink(it));
 
        execute_next_frame();
        if (autocvar_sv_autopause && !server_is_dedicated) Pause_TryPause(true);
@@ -191,7 +191,7 @@ void StartFrame()
        }
 #endif
 
-       FOREACH_ENTITY_FLOAT(csqcprojectile_clientanimate, true, CSQCProjectile_Check(it));
+       IL_EACH(g_projectiles, it.csqcprojectile_clientanimate, CSQCProjectile_Check(it));
 
        if (RedirectionThink()) return;
 
@@ -229,7 +229,7 @@ void StartFrame()
        MUTATOR_CALLHOOK(SV_StartFrame);
 
     FOREACH_CLIENT(true, GlobalStats_update(it));
-    FOREACH_ENTITY_CLASS(STR_PLAYER, IS_FAKE_CLIENT(it), PlayerPostThink(it));
+    IL_EACH(g_players, IS_FAKE_CLIENT(it), PlayerPostThink(it));
 }
 
 .vector originjitter;
index 1e71d33445cb22026ab772cd914f3911a34f7c35..254130f88c443cd4105e65ed20210faa4bbbb849 100644 (file)
@@ -97,41 +97,41 @@ spawnfunc(target_init)
 // weapon give ent from defrag
 void target_give_init(entity this)
 {
-       entity targ;
-       for (targ = NULL; (targ = find(targ, targetname, this.target)); ) {
-               if (targ.classname == "weapon_rocketlauncher" || targ.classname == "weapon_devastator") {
-                       this.ammo_rockets += targ.count * WEP_CVAR(devastator, ammo);
+       IL_EACH(g_items, it.targetname == this.target,
+       {
+               if (it.classname == "weapon_rocketlauncher" || it.classname == "weapon_devastator") {
+                       this.ammo_rockets += it.count * WEP_CVAR(devastator, ammo);
                        this.netname = "devastator";
                }
-               else if (targ.classname == "weapon_plasmagun") {
-                       this.ammo_rockets += targ.count * WEP_CVAR_PRI(hagar, ammo); // WEAPONTODO
+               else if (it.classname == "weapon_plasmagun") {
+                       this.ammo_rockets += it.count * WEP_CVAR_PRI(hagar, ammo); // WEAPONTODO
                        if(this.netname == "")
                                this.netname = "hagar";
                        else
                                this.netname = strcat(this.netname, " hagar");
                }
-               else if (targ.classname == "weapon_bfg") {
-                       this.ammo_cells += targ.count * WEP_CVAR_PRI(crylink, ammo);
+               else if (it.classname == "weapon_bfg") {
+                       this.ammo_cells += it.count * WEP_CVAR_PRI(crylink, ammo);
                        if(this.netname == "")
                                this.netname = "crylink";
                        else
                                this.netname = strcat(this.netname, " crylink");
                }
-               else if (targ.classname == "weapon_grenadelauncher" || targ.classname == "weapon_mortar") {
-                       this.ammo_rockets += targ.count * WEP_CVAR_PRI(mortar, ammo); // WEAPONTODO
+               else if (it.classname == "weapon_grenadelauncher" || it.classname == "weapon_mortar") {
+                       this.ammo_rockets += it.count * WEP_CVAR_PRI(mortar, ammo); // WEAPONTODO
                        if(this.netname == "")
                                this.netname = "mortar";
                        else
                                this.netname = strcat(this.netname, " mortar");
                }
-               else if (targ.classname == "item_armor_body")
+               else if (it.classname == "item_armor_body")
                        this.armorvalue = 100;
-               else if (targ.classname == "item_health_mega")
+               else if (it.classname == "item_health_mega")
                        this.health = 200;
-               //remove(targ); // removing ents in init functions causes havoc, workaround:
-        setthink(targ, SUB_Remove);
-        targ.nextthink = time;
-       }
+               //remove(it); // removing ents in init functions causes havoc, workaround:
+        setthink(it, SUB_Remove);
+        it.nextthink = time;
+       });
        this.spawnflags = 2;
        spawnfunc_target_items(this);
        InitializeEntity(this, target_init_verify, INITPRIO_FINDTARGET);
index 8c6c0eaac6f4283f231ff11fc4438e22f523801f..56df6c3a2c47e615562c1bd190eba45241536c3f 100644 (file)
@@ -21,12 +21,10 @@ void Send_WeaponComplain(entity e, float wpn, float type)
 void Weapon_whereis(Weapon this, entity cl)
 {
        if (!autocvar_g_showweaponspawns) return;
-       FOREACH_ENTITY_FLOAT(weapon, this.m_id,
+       IL_EACH(g_items, it.weapon == this.m_id,
        {
                if (it.classname == "droppedweapon" && autocvar_g_showweaponspawns < 2)
                        continue;
-               if (!(it.flags & FL_ITEM))
-                       continue;
                entity wp = WaypointSprite_Spawn(
                        WP_Weapon,
                        -2, 0,