From 3fa8f46190045139027b44248a828e93d52f635a Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Mon, 21 Oct 2013 13:18:56 +0200 Subject: [PATCH] Major improvements. More tunables. More fun. Better mincount handling. Teamplay support. --- qcsrc/server/item_ammo.qc | 135 +++++++++++++++++++++++++------------- 1 file changed, 91 insertions(+), 44 deletions(-) diff --git a/qcsrc/server/item_ammo.qc b/qcsrc/server/item_ammo.qc index ad5edb52e..93d6a8a85 100644 --- a/qcsrc/server/item_ammo.qc +++ b/qcsrc/server/item_ammo.qc @@ -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 -- 2.39.2