]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Major improvements. More tunables. More fun. Better mincount handling. Teamplay support.
authorRudolf Polzer <divverent@xonotic.org>
Mon, 21 Oct 2013 11:18:56 +0000 (13:18 +0200)
committerRudolf Polzer <divverent@xonotic.org>
Mon, 21 Oct 2013 11:19:14 +0000 (13:19 +0200)
qcsrc/server/item_ammo.qc

index ad5edb52e33a241d598332a652bf9d6cc873bb83..93d6a8a8551d6043bfee1af1cbfdb928a816f0a8 100644 (file)
@@ -1,5 +1,18 @@
 typedef void(float id, float itemtype, void() spawnfunc) item_ammo_acceptor;
 
+float autocvar_g_balance_ammodistribution_nudgevalue = 0;
+float autocvar_g_balance_ammodistribution_inner_exponent = -1;
+float autocvar_g_balance_ammodistribution_outer_exponent = 2;
+float autocvar_g_balance_ammodistribution_outer_nonmatch_exponent = -2;
+float autocvar_g_balance_ammodistribution_p3distance = 96;
+float autocvar_g_balance_ammodistribution_p2distance = 512;
+// NOTE: these also exist per weapon
+float autocvar_g_balance_ammodistribution_modifier_shells = 1;
+float autocvar_g_balance_ammodistribution_modifier_bullets = 1;
+float autocvar_g_balance_ammodistribution_modifier_cells = 1;
+float autocvar_g_balance_ammodistribution_modifier_rockets = 1;
+float autocvar_g_balance_ammodistribution_modifier_fuel = 1;
+
 #define ITEM_AMMO_COUNT 5
 void() item_ammo_spawnfunc(float i)
 {
@@ -14,6 +27,34 @@ void() item_ammo_spawnfunc(float i)
        }
        return spawnfunc_item_shells;
 };
+float item_ammo_weaponmodifier(float w)
+{
+       // autocvars are inconvenient here
+       float m = cvar(strcat("g_balance_ammodistribution_modifier_", get_weaponinfo(w).netname));
+       if (m == 0)
+               return 1;
+       if (m < 0)
+               return 0;
+       return m;
+}
+float item_ammo_modifier(float i)
+{
+       float m = 0;
+       switch (i)
+       {
+               case 0: m = autocvar_g_balance_ammodistribution_modifier_shells;
+               case 1: m = autocvar_g_balance_ammodistribution_modifier_bullets;
+               case 2: m = autocvar_g_balance_ammodistribution_modifier_cells;
+               case 3: m = autocvar_g_balance_ammodistribution_modifier_rockets;
+               case 4: m = autocvar_g_balance_ammodistribution_modifier_fuel;
+               default: error("item_ammo_wtf");
+       }
+       if (m == 0)
+               return 1;
+       if (m < 0)
+               return 0;
+       return m;
+};
 float item_ammo_type(float i)
 {
        switch (i)
@@ -33,13 +74,6 @@ float item_ammo_count[ITEM_AMMO_COUNT];
 .float item_ammo_priority[ITEM_AMMO_COUNT];
 .float item_ammo_chosen_type;
 
-float autocvar_g_balance_ammodistribution_nudgevalue = 0;
-float autocvar_g_balance_ammodistribution_inner_exponent = -1;
-float autocvar_g_balance_ammodistribution_outer_exponent = 2;
-float autocvar_g_balance_ammodistribution_outer_nonmatch_exponent = -2;
-float autocvar_g_balance_ammodistribution_p3distance = 96;
-float autocvar_g_balance_ammodistribution_p2distance = 512;
-
 float item_ammo_picked;
 void item_ammo_pick()
 {
@@ -60,6 +94,13 @@ void item_ammo_pick()
        for (a = ammolist; a; a = a.chain)
                ++n_a;
 
+       float n_teams = 1;
+       if (teamplay)
+       {
+               CheckAllowedTeams(world);
+               n_teams = (c1 >= 0) + (c2 >= 0) + (c3 >= 0) + (c4 >= 0);
+       }
+
        // Find out how many we want of each item.
        for (i = 0; i < ITEM_AMMO_COUNT; ++i)
        {
@@ -89,16 +130,19 @@ void item_ammo_pick()
                for (i = 0; i < ITEM_AMMO_COUNT; ++i)
                        if (get_weaponinfo(w.weapon).items & item_ammo_type(i))
                        {
-                               item_ammo_count[i] += c;
-                               item_ammo_mincount[i] = 1;
+                               item_ammo_count[i] += item_ammo_modifier(i) * item_ammo_weaponmodifier(w.weapon) * c;
+                               item_ammo_mincount[i] = n_teams;
                        }
        }
+       float n_count = 0;
        float n_mincount = 0;
        for (i = 0; i < ITEM_AMMO_COUNT; ++i)
-               if (item_ammo_mincount[i])
-                       n_mincount += item_ammo_mincount[i];
+       {
+               n_count += item_ammo_count[i];
+               n_mincount += item_ammo_mincount[i];
+       }
        for (i = 0; i < ITEM_AMMO_COUNT; ++i)
-               item_ammo_count[i] = item_ammo_mincount[i] + max(0, ceil(item_ammo_count[i] * (n_a - n_mincount) / n_w + autocvar_g_balance_ammodistribution_nudgevalue));
+               item_ammo_count[i] = item_ammo_mincount[i] + max(0, ceil(item_ammo_count[i] * (n_a - n_mincount) / n_count + autocvar_g_balance_ammodistribution_nudgevalue));
 
        // Find the weights and priorities.
        for (a = ammolist; a; a = a.chain)
@@ -126,20 +170,22 @@ void item_ammo_pick()
                                a.item_ammo_weight[i] = 0;
                        else
                                a.item_ammo_weight[i] = pow(sum, autocvar_g_balance_ammodistribution_outer_exponent) * weight;
-                       if (forbid || mindist < 0)
+                       if (mindist < 0)
                                a.item_ammo_priority[i] = 0;
+                       else if (forbid)
+                               a.item_ammo_priority[i] = 1;
                        else if (mindist <= autocvar_g_balance_ammodistribution_p3distance)
-                               a.item_ammo_priority[i] = 3;
+                               a.item_ammo_priority[i] = 4;
                        else if (mindist <= autocvar_g_balance_ammodistribution_p2distance)
-                               a.item_ammo_priority[i] = 2;
+                               a.item_ammo_priority[i] = 3;
                        else
-                               a.item_ammo_priority[i] = 1;
+                               a.item_ammo_priority[i] = 2;
                        totalsum += sum;
                }
                for (i = 0; i < ITEM_AMMO_COUNT; ++i)
                {
                        float weight = a.(Item_CounterField(item_ammo_type(i)));
-                       if (a.item_ammo_priority[i] == 0)
+                       if (a.item_ammo_weight[i] == 0)
                                a.item_ammo_weight[i] = pow(totalsum, autocvar_g_balance_ammodistribution_outer_nonmatch_exponent) * weight;
                }
        }
@@ -149,40 +195,41 @@ void item_ammo_pick()
                a.item_ammo_chosen_type = -1;
 
        // Distribute them properly.
-       float matchmode;
-       for (matchmode = 0; matchmode < 2; ++matchmode)
+       while (n_a > 0)
        {
-               while (n_a > 0)
+               // Randomly pick one of the remaining item spawn points, and a
+               // corresponding item type. Honor priorities and weights.
+               RandomSelection_Init();
+               for (a = ammolist; a; a = a.chain)
+                       if (a.item_ammo_chosen_type == -1)
+                               for (i = 0; i < ITEM_AMMO_COUNT; ++i)
+                                       if (((n_a <= n_mincount) ? item_ammo_mincount[i] : item_ammo_count[i]) > 0)
+                                               RandomSelection_Add(a, i, string_null, a.item_ammo_weight[i], a.item_ammo_priority[i]);
+               a = RandomSelection_chosen_ent;
+               i = RandomSelection_chosen_float;
+
+               if (!a)
                {
-                       // Randomly pick one of the remaining item spawn points, and a
-                       // corresponding item type. Honor priorities and weights.
-                       RandomSelection_Init();
-                       for (a = ammolist; a; a = a.chain)
-                               if (a.item_ammo_chosen_type == -1)
-                                       for (i = 0; i < ITEM_AMMO_COUNT; ++i)
-                                               if ((matchmode ? item_ammo_count[i] : item_ammo_mincount[i]) > 0)
-                                                       RandomSelection_Add(a, i, string_null, a.item_ammo_weight[i], a.item_ammo_priority[i]);
-                       a = RandomSelection_chosen_ent;
-                       i = RandomSelection_chosen_float;
-
-                       if (!a)
+                       if (n_mincount >= 0)
                        {
-                               // First round: just go to second round.
-                               if (matchmode == 0)
-                                       continue;
-                               error("Nothing to select.");
+                               backtrace("Nothing to select. Retrying without mincount... (BTW: FIX YOUR MAP AND/OR THIS CODE)");
+                               n_mincount = 0;
+                               continue;
                        }
+                       error("Nothing to select.");
+               }
 
-                       // Assign the selected item type to the selected item.
-                       a.item_ammo_chosen_type = i;
+               // Assign the selected item type to the selected item.
+               a.item_ammo_chosen_type = i;
 
-                       print(sprintf("%v: %s -> %s\n", a.origin, a.save_classname, Item_CounterFieldName(item_ammo_type(i))));
+               print(sprintf("%v: %s -> %s\n", a.origin, a.save_classname, Item_CounterFieldName(item_ammo_type(i))));
 
-                       // Decrease the count of remaining items.
-                       --item_ammo_mincount[i];
-                       --item_ammo_count[i];
-                       --n_a;
-               }
+               // Decrease the count of remaining items.
+               if (item_ammo_mincount[i] > 0)
+                       --n_mincount;
+               --item_ammo_mincount[i];
+               --item_ammo_count[i];
+               --n_a;
        }
 
        // SPAWN SPAWN SPAWN