]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into terencehill/bot_item_rating
authorterencehill <piuntn@gmail.com>
Mon, 30 Jan 2017 10:44:23 +0000 (11:44 +0100)
committerterencehill <piuntn@gmail.com>
Mon, 30 Jan 2017 10:44:23 +0000 (11:44 +0100)
qcsrc/common/items/item/armor.qh
qcsrc/common/items/item/health.qh
qcsrc/common/t_items.qc
qcsrc/common/t_items.qh
qcsrc/server/bot/default/bot.qc
qcsrc/server/bot/default/bot.qh
qcsrc/server/bot/default/havocbot/roles.qc
qcsrc/server/bot/default/navigation.qc

index f153bf06e3e64e681c1811a78561708f0e7965b8..bc2aa654451d9129b20602a82c6211dce7a05c23 100644 (file)
@@ -6,7 +6,7 @@ CLASS(Armor, Pickup)
     ATTRIB(Armor, m_mins, vector, '-16 -16 0');
     ATTRIB(Armor, m_maxs, vector, '16 16 48');
     ATTRIB(Armor, m_pickupevalfunc, float(entity player, entity item), healtharmor_pickupevalfunc);
-    ATTRIB(Armor, m_botvalue, int, 3000);
+    ATTRIB(Armor, m_botvalue, int, 5000);
 #endif
 ENDCLASS(Armor)
 
index 1fc544a40073e7a17b31ee327d394c5e01c603df..9366bc4617622bfd0e6ad67e4bd826bcbea5a8e3 100644 (file)
@@ -6,7 +6,7 @@ CLASS(Health, Pickup)
     ATTRIB(Health, m_mins, vector, '-16 -16 0');
     ATTRIB(Health, m_maxs, vector, '16 16 48');
     ATTRIB(Health, m_pickupevalfunc, float(entity player, entity item), healtharmor_pickupevalfunc);
-    ATTRIB(Health, m_botvalue, int, 2500);
+    ATTRIB(Health, m_botvalue, int, 5000);
 #endif
 ENDCLASS(Health)
 
index 9aab742d0198560e651cccc71c8bae12beadd517..6d4fa7720f16da31197a59bcb30c239e12cdf7da 100644 (file)
@@ -957,7 +957,16 @@ float weapon_pickupevalfunc(entity player, entity item)
                        return 0;
                return ammo_pickupevalfunc(player, item);
        }
-       return item.bot_pickupbasevalue;
+
+       // reduce weapon value if bot already got a good arsenal
+       float c = 1;
+       int weapons_value = 0;
+       FOREACH(Weapons, it != WEP_Null && (player.weapons & it.m_wepset), {
+               weapons_value += it.bot_pickupbasevalue;
+       });
+       c -= bound(0, weapons_value / 20000, 1) * 0.5;
+
+       return item.bot_pickupbasevalue * c;
 }
 
 float ammo_pickupevalfunc(entity player, entity item)
@@ -1006,48 +1015,56 @@ float ammo_pickupevalfunc(entity player, entity item)
        if (need_shells)
        if (item.ammo_shells)
        if (player.ammo_shells < g_pickup_shells_max)
-               c = (player.ammo_shells + item.ammo_shells) / player.ammo_shells;
+               c = item.ammo_shells / player.ammo_shells;
        if (need_nails)
        if (item.ammo_nails)
        if (player.ammo_nails < g_pickup_nails_max)
-               c = (player.ammo_nails + item.ammo_nails) / player.ammo_nails;
+               c = item.ammo_nails / player.ammo_nails;
        if (need_rockets)
        if (item.ammo_rockets)
        if (player.ammo_rockets < g_pickup_rockets_max)
-               c = (player.ammo_rockets + item.ammo_rockets) / player.ammo_rockets;
+               c = item.ammo_rockets / player.ammo_rockets;
        if (need_cells)
        if (item.ammo_cells)
        if (player.ammo_cells < g_pickup_cells_max)
-               c = (player.ammo_cells + item.ammo_cells) / player.ammo_cells;
+               c = item.ammo_cells / player.ammo_cells;
        if (need_plasma)
        if (item.ammo_plasma)
        if (player.ammo_plasma < g_pickup_plasma_max)
-               c = (player.ammo_plasma + item.ammo_plasma) / player.ammo_plasma;
+               c = item.ammo_plasma / player.ammo_plasma;
        if (need_fuel)
        if (item.ammo_fuel)
        if (player.ammo_fuel < g_pickup_fuel_max)
-               c = (player.ammo_fuel + item.ammo_fuel) / player.ammo_fuel;
+               c = item.ammo_fuel / player.ammo_fuel;
 
-       rating *= min(3, c);
+       rating *= min(2, c);
        if(wpn)
-               // Skilled bots will grab more
-               rating += wpn.bot_pickupbasevalue * (0.1 + 0.1 * bound(0, skill / 10, 1));
+               rating += wpn.bot_pickupbasevalue * 0.1;
        return rating;
 }
 
+.int item_group;
+.int item_group_count;
 float healtharmor_pickupevalfunc(entity player, entity item)
 {
        float c = 0;
        float rating = item.bot_pickupbasevalue;
 
-       if (item.armorvalue)
+       float itemarmor = item.armorvalue;
+       float itemhealth = item.health;
+       if(item.item_group)
+       {
+               itemarmor *= min(4, item.item_group_count);
+               itemhealth *= min(4, item.item_group_count);
+       }
+       if (itemarmor)
        if (player.armorvalue < item.max_armorvalue)
-               c = (player.armorvalue + player.health + item.armorvalue) / (max(1, player.armorvalue + player.health));
-       if (item.health)
+               c = itemarmor / max(1, player.armorvalue * 2/3 + player.health * 1/3);
+       if (itemhealth)
        if (player.health < item.max_health)
-               c = (player.health + item.health) / (max(1, player.health));
+               c = itemhealth / max(1, player.health);
 
-       rating *= min(3, c);
+       rating *= min(2, c);
        return rating;
 }
 
@@ -1269,6 +1286,8 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                delete(this);
                return;
        }
+
+       setItemGroup(this);
 }
 
 void StartItem(entity this, GameItem def)
@@ -1281,6 +1300,54 @@ void StartItem(entity this, GameItem def)
        );
 }
 
+#define IS_SMALL(def) ((def.instanceOfHealth && def == ITEM_HealthSmall) || (def.instanceOfArmor && def == ITEM_ArmorSmall))
+int group_count = 1;
+
+void setItemGroup(entity this)
+{
+       if(!IS_SMALL(this.itemdef))
+               return;
+
+       FOREACH_ENTITY_RADIUS(this.origin, 120, (it != this) && IS_SMALL(it.itemdef),
+       {
+               if(!this.item_group)
+               {
+                       if(!it.item_group)
+                       {
+                               it.item_group = group_count;
+                               group_count++;
+                       }
+                       this.item_group = it.item_group;
+               }
+               else // spawning item is already part of a item_group X
+               {
+                       if(!it.item_group)
+                               it.item_group = this.item_group;
+                       else if(it.item_group != this.item_group) // found an item near the spawning item that is part of a different item_group Y
+                       {
+                               int grY = it.item_group;
+                               // move all items of item_group Y to item_group X
+                               FOREACH_ENTITY(IS_SMALL(it.itemdef),
+                               {
+                                       if(it.item_group == grY)
+                                               it.item_group = this.item_group;
+                               });
+                       }
+               }
+       });
+}
+
+void setItemGroupCount()
+{
+       for (int k = 1; k <= group_count; k++)
+       {
+               int count = 0;
+               FOREACH_ENTITY(IS_SMALL(it.itemdef) && it.item_group == k, { count++; });
+               if (count)
+                       FOREACH_ENTITY(IS_SMALL(it.itemdef) && it.item_group == k, { it.item_group_count = count; });
+       }
+}
+
 spawnfunc(item_rockets)
 {
        if(!this.ammo_rockets)
index f5a310562b8cfc189e9a0260758141eae8eef980..1b2293bcff0651d442032c328d7a0455783adb3b 100644 (file)
@@ -114,6 +114,8 @@ float healtharmor_pickupevalfunc(entity player, entity item);
 .entity itemdef;
 void _StartItem(entity this, entity def, float defaultrespawntime, float defaultrespawntimejitter);
 
+void setItemGroup(entity this);
+void setItemGroupCount();
 
 float GiveWeapon(entity e, float wpn, float op, float val);
 
index 160f8ec90b4772807ee12755442d675129ff5f33..2fb0a43c2b150cc9d726336a7ed095996b865902 100644 (file)
@@ -46,6 +46,7 @@ entity bot_spawn()
        entity bot = spawnclient();
        if (bot)
        {
+               setItemGroupCount();
                currentbots = currentbots + 1;
                bot_setnameandstuff(bot);
                ClientConnect(bot);
index f615c040360f7f2bbbc85f296137c60c1c8c2765..b72fad9bd600248601794130a2cf0f505c110991 100644 (file)
@@ -62,6 +62,7 @@ entity bot_list;
 
 .float bot_pickup;
 .float bot_pickupbasevalue;
+.bool bot_pickup_respawning;
 .float bot_canfire;
 .float bot_strategytime;
 
index f57a18fed6c39a1bb4a5d7b3e63506996d817d13..5c25806365f367d1b3337cbae77b1231018282aa 100644 (file)
@@ -23,8 +23,26 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float
        {
                rating = 0;
 
+               if(!it.solid)
+               {
+                       if(!it.scheduledrespawntime)
+                               continue;
+                       if(it.respawntime < 30 || (it.respawntimejitter && !it.itemdef.instanceOfPowerup))
+                               continue;
+
+                       float t = 0;
+                       if(it.itemdef.instanceOfPowerup)
+                               t = bound(0, skill / 10, 1) * 6;
+                       else if(skill >= 9)
+                               t = 4;
+
+                       if(time < it.scheduledrespawntime - t)
+                               continue;
+
+                       it.bot_pickup_respawning = true;
+               }
                o = (it.absmin + it.absmax) * 0.5;
-               if(!it.solid || vdist(o - org, >, sradius) || (it == this.ignoregoal && time < this.ignoregoaltime) )
+               if(vdist(o - org, >, sradius) || (it == this.ignoregoal && time < this.ignoregoaltime) )
                        continue;
 
                // Check if the item can be picked up safely
@@ -105,6 +123,7 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float
        });
 }
 
+#define BOT_RATING_ENEMY 2500
 void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius)
 {
        if (autocvar_bot_nofire)
@@ -114,6 +133,8 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org
        if(this.waterlevel>WATERLEVEL_WETFEET)
                return;
 
+       ratingscale = ratingscale * 0.00005; // enemies are rated around 20000 already
+
        int t;
 
        FOREACH_CLIENT(IS_PLAYER(it) && bot_shouldattack(this, it), LAMBDA(
@@ -147,8 +168,17 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org
                //               adding a player as a goal seems to be quite dangerous, especially on space maps
                //               remove hack in navigation_poptouchedgoals() after performing this change
 
-               t = (this.health + this.armorvalue ) / (it.health + it.armorvalue );
-               navigation_routerating(this, it, t * ratingscale, 2000);
+               t = ((this.health + this.armorvalue) - (it.health + it.armorvalue)) / 150;
+               t = bound(0, 1 + t, 3);
+               if (skill > 3)
+               {
+                       if (time < this.strength_finished - 1) t += 0.5;
+                       if (time < it.strength_finished - 1) t -= 0.5;
+               }
+               t += max(0, 8 - skill) * 0.05; // less skilled bots attack more mindlessly
+               ratingscale *= t;
+               if (ratingscale > 0)
+                       navigation_routerating(this, it, ratingscale * BOT_RATING_ENEMY, 2000);
        ));
 }
 
index 4c8982e9457a22d9614a6d4aed2d2bec00ab46fa..d6bb2195f64ea9d4a3248f88bc5ec2f55e668f6f 100644 (file)
@@ -897,6 +897,13 @@ void navigation_poptouchedgoals(entity this)
                }
        }
 
+       if(this.goalcurrent.bot_pickup_respawning)
+       {
+               if(!this.goalcurrent.solid)
+                       return;
+               this.goalcurrent.bot_pickup_respawning = false;
+       }
+
        // If for some reason the bot is closer to the next goal, pop the current one
        if(this.goalstack01 && !wasfreed(this.goalstack01))
        if(vlen2(this.goalcurrent.origin - this.origin) > vlen2(this.goalstack01.origin - this.origin))