]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/t_items.qc
Fix bots waiting for a teamed item to spawn again once they got it (e.g. megas and...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / t_items.qc
index c19f303a6be66d9396f55d988d459d5132effa56..c116b440c42a4686ff8b034f0e3b800e2092c8fd 100644 (file)
@@ -631,32 +631,43 @@ void Item_ScheduleRespawnIn(entity e, float t)
        }
 }
 
-AUTOCVAR(g_pickup_respawntime_scaling_a, float, 0.0, "Scale respawn time according to a*rt / (p+b) + c*rt where rt is normal respawn time and p number of players");
-AUTOCVAR(g_pickup_respawntime_scaling_b, float, 0.0, "Scale respawn time according to a*rt / (p+b) + c*rt where rt is normal respawn time and p number of players");
-AUTOCVAR(g_pickup_respawntime_scaling_c, float, 1.0, "Scale respawn time according to a*rt / (p+b) + c*rt where rt is normal respawn time and p number of players");
+AUTOCVAR(g_pickup_respawntime_scaling_reciprocal, float, 0.0, "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `reciprocal` (with `offset` and `linear` set to 0) can be used to achieve a constant number of items spawned *per player*");
+AUTOCVAR(g_pickup_respawntime_scaling_offset, float, 0.0, "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `offset` offsets the curve left or right - the results are not intuitive and I recommend plotting the respawn time and the number of items per player to see what's happening");
+AUTOCVAR(g_pickup_respawntime_scaling_linear, float, 1.0, "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `linear` can be used to simply scale the respawn time linearly");
+
+float adjust_respawntime(float normal_respawntime) {
+       float r = autocvar_g_pickup_respawntime_scaling_reciprocal;
+       float o = autocvar_g_pickup_respawntime_scaling_offset;
+       float l = autocvar_g_pickup_respawntime_scaling_linear;
+
+       if (r == 0 && l == 1) {
+               return normal_respawntime;
+       }
+
+       CheckAllowedTeams(NULL);
+       GetTeamCounts(NULL);
+       int players = 0;
+       if (c1 != -1) players += c1;
+       if (c2 != -1) players += c2;
+       if (c3 != -1) players += c3;
+       if (c4 != -1) players += c4;
+
+       if (players >= 2) {
+               return normal_respawntime * (r / (players + o) + l);
+       } else {
+               return normal_respawntime;
+       }
+}
+
 void Item_ScheduleRespawn(entity e)
 {
        if(e.respawntime > 0)
        {
                Item_Show(e, 0);
 
-               CheckAllowedTeams(NULL);
-               GetTeamCounts(NULL);
-               int players = 0;
-               if (c1 != -1) players += c1;
-               if (c2 != -1) players += c2;
-               if (c3 != -1) players += c3;
-               if (c4 != -1) players += c4;
-               float adjusted_respawntime;
-               if (players >= 2) {
-                       float a = autocvar_g_pickup_respawntime_scaling_a;
-                       float b = autocvar_g_pickup_respawntime_scaling_b;
-                       float c = autocvar_g_pickup_respawntime_scaling_c;
-                       adjusted_respawntime = a * e.respawntime / (players + b) + c * e.respawntime;
-               } else {
-                       adjusted_respawntime = e.respawntime;
-               }
-               //LOG_INFOF("item %s will respawn in %f\n", e.classname, adjusted_respawntime);
+               float adjusted_respawntime = adjust_respawntime(e.respawntime);
+               //LOG_INFOF("item %s will respawn in %f", e.classname, adjusted_respawntime);
+
                // range: adjusted_respawntime - respawntimejitter .. adjusted_respawntime + respawntimejitter
                float actual_time = adjusted_respawntime + crandom() * e.respawntimejitter;
                Item_ScheduleRespawnIn(e, actual_time);
@@ -671,46 +682,28 @@ void Item_ScheduleInitialRespawn(entity e)
        Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : ITEM_RESPAWNTIME_INITIAL(e)));
 }
 
-float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax, float mode)
+float Item_GiveAmmoTo(entity item, entity player, int resource_type, float ammomax)
 {
-       if (!item.(ammotype))
-               return false;
-
-       if (item.spawnshieldtime)
+       float amount = GetResourceAmount(item, resource_type);
+       if (amount == 0)
        {
-               if ((player.(ammotype) < ammomax) || item.pickup_anyway > 0)
-               {
-                       player.(ammotype) = bound(player.(ammotype), ammomax, player.(ammotype) + item.(ammotype));
-                       goto YEAH;
-               }
+               return false;
        }
-       else if(g_weapon_stay == 2)
+       float player_amount = GetResourceAmount(player, resource_type);
+       if (item.spawnshieldtime)
        {
-               float mi = min(item.(ammotype), ammomax);
-               if (player.(ammotype) < mi)
+               if ((player_amount >= ammomax) && (item.pickup_anyway <= 0))
                {
-                       player.(ammotype) = mi;
-                       goto YEAH;
+                       return false;
                }
+               GiveResourceWithLimit(player, resource_type, amount, ammomax);
+               return true;
        }
-
-       return false;
-
-LABEL(YEAH)
-       switch(mode)
+       if (g_weapon_stay != 2)
        {
-               case ITEM_MODE_FUEL:
-                       player.pauserotfuel_finished = max(player.pauserotfuel_finished, time + autocvar_g_balance_pause_fuel_rot);
-                       break;
-               case ITEM_MODE_HEALTH:
-                       player.pauserothealth_finished = max(player.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot);
-                       break;
-               case ITEM_MODE_ARMOR:
-                       player.pauserotarmor_finished = max(player.pauserotarmor_finished, time + autocvar_g_balance_pause_armor_rot);
-                       break;
-               default:
-                       break;
+               return false;
        }
+       GiveResourceWithLimit(player, resource_type, amount, min(amount, ammomax));
        return true;
 }
 
@@ -740,16 +733,14 @@ float Item_GiveTo(entity item, entity player)
                        }
                }
        }
-
-       pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
-       pickedup |= Item_GiveAmmoTo(item, player, ammo_shells, g_pickup_shells_max, ITEM_MODE_NONE);
-       pickedup |= Item_GiveAmmoTo(item, player, ammo_nails, g_pickup_nails_max, ITEM_MODE_NONE);
-       pickedup |= Item_GiveAmmoTo(item, player, ammo_rockets, g_pickup_rockets_max, ITEM_MODE_NONE);
-       pickedup |= Item_GiveAmmoTo(item, player, ammo_cells, g_pickup_cells_max, ITEM_MODE_NONE);
-       pickedup |= Item_GiveAmmoTo(item, player, ammo_plasma, g_pickup_plasma_max, ITEM_MODE_NONE);
-       pickedup |= Item_GiveAmmoTo(item, player, health, item.max_health, ITEM_MODE_HEALTH);
-       pickedup |= Item_GiveAmmoTo(item, player, armorvalue, item.max_armorvalue, ITEM_MODE_ARMOR);
-
+       pickedup |= Item_GiveAmmoTo(item, player, RESOURCE_HEALTH, item.max_health);
+       pickedup |= Item_GiveAmmoTo(item, player, RESOURCE_ARMOR, item.max_armorvalue);
+       pickedup |= Item_GiveAmmoTo(item, player, RESOURCE_SHELLS, g_pickup_shells_max);
+       pickedup |= Item_GiveAmmoTo(item, player, RESOURCE_BULLETS, g_pickup_nails_max);
+       pickedup |= Item_GiveAmmoTo(item, player, RESOURCE_ROCKETS, g_pickup_rockets_max);
+       pickedup |= Item_GiveAmmoTo(item, player, RESOURCE_CELLS, g_pickup_cells_max);
+       pickedup |= Item_GiveAmmoTo(item, player, RESOURCE_PLASMA, g_pickup_plasma_max);
+       pickedup |= Item_GiveAmmoTo(item, player, RESOURCE_FUEL, g_pickup_fuel_max);
        if (item.itemdef.instanceOfWeaponPickup)
        {
                WepSet w;
@@ -910,6 +901,7 @@ LABEL(pickup)
                                if(it.itemdef) // is a registered item
                                {
                                        Item_Show(it, -1);
+                                       it.scheduledrespawntime = 0;
                                        RandomSelection_AddEnt(it, it.cnt, 0);
                                }
                        });