]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Intrusify bot targets
authorMario <mario@smbclan.net>
Mon, 22 Aug 2016 06:42:38 +0000 (16:42 +1000)
committerMario <mario@smbclan.net>
Mon, 22 Aug 2016 06:42:38 +0000 (16:42 +1000)
12 files changed:
qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/triggers/func/breakable.qc
qcsrc/common/turrets/sv_turrets.qc
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/client.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/mutators/mutator/gamemode_invasion.qc

index 643a02954c336b02b7650462ee75dc7d06bd663d..3f48fd15a91b7ee50c5255ab04f96eeffacdcbe9 100644 (file)
@@ -196,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;
                }
 
@@ -566,6 +570,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;
@@ -917,6 +922,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;
@@ -979,6 +985,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);
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 b922a65b6af994501fc21bc0e5d8152e190eef83..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;
        }
index dabb7ee35dfcdbcb8845f4014355be79168ae8de..adad91a0b9e0d866f1d64eee068a6d01696efcd1 100644 (file)
@@ -1252,6 +1252,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 39f959d14b9f03f851f6b8edebf6d3efd90008e3..a010ba2c44568280543aa6c0de459a5ce4e98510 100644 (file)
@@ -1077,6 +1077,7 @@ void vehicles_spawn(entity this)
        this.takedamage                 = DAMAGE_AIM;
        this.deadflag                   = DEAD_NO;
        this.bot_attack                 = true;
+       IL_PUSH(g_bot_targets, this);
        this.flags                              = FL_NOTARGET;
        this.avelocity                  = '0 0 0';
        this.velocity                   = '0 0 0';
@@ -1161,6 +1162,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 d44ee7ec20842fcc2bdb2bbf4a506356e5c1463f..a99bce47ed9a9dd5527e0defb6586d3ba6c939c3 100644 (file)
@@ -463,7 +463,7 @@ METHOD(Devastator, wr_aim, void(entity thiswep, entity actor))
         IL_EACH(g_projectiles, it.realowner == actor && it.classname == "rocket",
         {
             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);
@@ -489,7 +489,7 @@ METHOD(Devastator, wr_aim, void(entity thiswep, entity actor))
             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
index a3b356954af68f47a0b07d76ac61aa5d81e4f204..568fb6bd4451c3b7799c65dc2b109348d5cd2ba5 100644 (file)
@@ -436,7 +436,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 +463,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 78a1f745d9e8d681e06a5db6f51ebba53c0639ef..cbb6a68b6d8504108c1842c2c41f0e4a69c9000b 100644 (file)
@@ -837,11 +837,28 @@ 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;
-       float rating, bestrating, hf;
-       vector eye, v;
        if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(this))
        {
                this.enemy = NULL;
@@ -880,81 +897,24 @@ void havocbot_chooseenemy(entity this)
        if (time < this.havocbot_chooseenemy_finished)
                return;
        this.havocbot_chooseenemy_finished = time + autocvar_bot_ai_enemydetectioninterval;
-       eye = this.origin + this.view_ofs;
-       best = NULL;
-       bestrating = 100000000;
-       head = head2 = findchainfloat(bot_attack, true);
-
-       // Backup hit flags
-       hf = this.dphitcontentsmask;
 
        // Search for enemies, if no enemy can be seen directly try to look through transparent objects
 
+       int myhit = this.dphitcontentsmask;
        this.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
 
-       bool scan_transparent = false;
-       bool scan_secondary_targets = false;
-       bool have_secondary_targets = false;
-       while(true)
+       entity best = havocbot_gettarget(this, false); // first try primary targets
+       if(!best)
+               best = havocbot_gettarget(this, true); // now try secondary targets
+       if(!best && this.weapons)
        {
-               scan_secondary_targets = false;
-LABEL(scan_targets)
-               for( ; head; head = head.chain)
-               {
-                       if(!scan_secondary_targets)
-                       {
-                               if(head.classname == "misc_breakablemodel")
-                               {
-                                       have_secondary_targets = true;
-                                       continue;
-                               }
-                       }
-                       else
-                       {
-                               if(head.classname != "misc_breakablemodel")
-                                       continue;
-                       }
-
-                       v = (head.absmin + head.absmax) * 0.5;
-                       rating = vlen(v - eye);
-                       if (rating<autocvar_bot_ai_enemydetectionradius)
-                       if (bestrating > rating)
-                       if (bot_shouldattack(this, head))
-                       {
-                               traceline(eye, v, true, this);
-                               if (trace_ent == head || trace_fraction >= 1)
-                               {
-                                       best = head;
-                                       bestrating = rating;
-                               }
-                       }
-               }
-
-               if(!best && have_secondary_targets && !scan_secondary_targets)
-               {
-                       scan_secondary_targets = true;
-                       // restart the loop
-                       head = head2;
-                       bestrating = 100000000;
-                       goto scan_targets;
-               }
-
-               // I want to do a second scan if no enemy was found or I don't have weapons
-               // TODO: Perform the scan when using the rifle (requires changes on the rifle code)
-               if(best || this.weapons) // || this.weapon == WEP_RIFLE.m_id
-                       break;
-               if(scan_transparent)
-                       break;
-
-               // Set flags to see through transparent objects
                this.dphitcontentsmask |= DPCONTENTS_OPAQUE;
-
-               head = head2;
-               scan_transparent = true;
+               best = havocbot_gettarget(this, false);
+               if(!best)
+                       best = havocbot_gettarget(this, true);
        }
 
-       // Restore hit flags
-       this.dphitcontentsmask = hf;
+       this.dphitcontentsmask = myhit;
 
        this.enemy = best;
        this.havocbot_stickenemy = true;
index 686829e3331b27eafcd16d059e3821045e0e59ea..9a38c2f6117fd78b2bed744648c53305c218cbf1 100644 (file)
@@ -294,6 +294,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);
@@ -632,6 +634,8 @@ void PutClientInServer(entity this)
 
                this.event_damage = PlayerDamage;
 
+               if(!this.bot_attack)
+                       IL_PUSH(g_bot_targets, this);
                this.bot_attack = true;
                this.monster_attack = true;
 
index 447d4a8ea88aa0bb7ebd119930c7bdcdf02a07b5..6fbff1a9679e79b72d982b9b122bfee1c66ac81a 100644 (file)
@@ -466,3 +466,6 @@ 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(); }
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 7083d3a8f607b00564338e2298d5cb0b91558e65..d43d504821e795aa2c2611107629dbe33416ed8b 100644 (file)
@@ -343,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;
 }