Tigranes said: ↑ The funny thing is that we could never prove the numbers are lying, unless we looked at the code... Click to expand...

Code: public override bool CheckForJammed() { ItemInstance_WeaponRanged itemInstance_WeaponRanged = this.pcStats.GetWeaponInstance() as ItemInstance_WeaponRanged; if (itemInstance_WeaponRanged == null) { return false; } if (itemInstance_WeaponRanged.CheckForJammed()) { this.PrintFloatingText(Language.Localize("Weapon Jam!", false), Color.get_red(), null, false); AudioManager.Play("Weapon_OnJam", base.get_transform()); EventInfo_WeaponJammed eventInfo_WeaponJammed = ObjectPool.Get<EventInfo_WeaponJammed>(); eventInfo_WeaponJammed.mob = this; eventInfo_WeaponJammed.weapon = itemInstance_WeaponRanged; eventInfo_WeaponJammed.isJammed = true; MonoBehaviourSingleton<EventManager>.GetInstance(false).Publish(eventInfo_WeaponJammed, false); return true; } return false; }

Code: // ItemInstance_WeaponRanged public int GetChanceToJam() { ItemTemplate_WeaponRanged itemTemplate_WeaponRanged = this.template as ItemTemplate_WeaponRanged; int num = itemTemplate_WeaponRanged.chanceToJam; foreach (ItemInstance_Mod current in this.mods) { num += (int)current.GetBonus("chanceToJam"); } num = Mathf.Clamp(num, 0, 100); return num; }

Code: public bool CheckForJammed() { int chanceToJam = this.GetChanceToJam(); int num = Random.Range(0, 100); if (num < chanceToJam) { this.SetJammed(true); return true; } return false; }



"A naive C implementation of a xorshift+ generator that passes all tests from the BigCrush suite (with an order of magnitude fewer failures than Mersenne Twister or WELL )" Click to expand...

Code: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace RNGTool { class MT_Random { // State of Random Generator private UInt32[] genState; private UInt32 index; // MT19937 uses 623 Entries, Accounting for 0 Index private const Int16 N = 624; // For Bit Shifting and Exclusive ORing // Reference For Bits - Hiroshima University C++ Code private const UInt32 UPPER_MASK = (UInt32)0x80000000; /* most significant bits */ private const UInt32 LOWER_MASK = (UInt32)0x7fffffff; /* least significant bits */ // Default Constructor public MT_Random() { UInt32 GenSeed = 1337; UInt32.TryParse((Environment.TickCount & Int32.MaxValue).ToString(), out GenSeed); // If no Seed is Provided use Time (Tick Count) inititialize(GenSeed); } // Seed Provided for constructor public MT_Random(UInt32 seed) { inititialize(seed); } // Initialize the Random Generator private void inititialize(UInt32 seed) { // Set Boundaries for This Algorithm genState = new UInt32[N]; index = 0; genState[0] = seed; // Initialize State of Generator // last 32 bits of(1812433253 * (State[i-1] xor (right shift by 30 bits(State[i-1]))) + i) // 0x6c078965 try { for (UInt16 i = 1; i < N; i++) { genState[i] = ((UInt32)1812433253 * (genState[i - 1] ^ (genState[i - 1] >> 30)) + i); } } catch(Exception ex) { ex.Message.ToString(); } } // Extract a tempered pseudorandom number based on the index-th value, // calling generate_numbers() every 624 numbers private UInt32 extract_number() { if(index == 0) { generate_numbers(); } /* Tempering */ UInt32 y = genState[index]; // y := y xor (right shift by 11 bits(y)) y ^= (y >> 11); // y := y xor (left shift by 7 bits(y) and (2636928640)) == 0x9d2c5680 y ^= (y << 7) & 0x9d2c5680; // y := y xor (left shift by 15 bits(y) and (4022730752)) // 0xefc60000 y ^= (y << 15) & 0xefc60000; // y := y xor (right shift by 18 bits(y)) y ^= (y >> 18); // index := (index + 1) mod 624 index = (index + 1) % 624; return y; } // Generate an array of 624 untempered numbers private void generate_numbers() { for (UInt32 i = 0; i <= 623; i++) { // bit 31 (32nd bit) of MT[i] UInt32 y = (genState[i] & 0x80000000) // bits 0-30 (first 31 bits) of MT[...] + (genState[(i + 1) % 624] & 0x7fffffff); // MT[i] := MT[(i + 397) mod 624] xor (right shift by 1 bit(y)) genState[i] = genState[(i + 397) % 624] ^ (y >> 1); // Check if Y is Odd Number if ((y % 2) != 0) { // MT[i] := MT[i] xor (2567483615) // 0x9908b0df genState[i] = genState[i] ^ 0x9908b0df; } } } // Reference: Jerry Coffin // Provided a Method to Give Range Values without introducing SKEW // Using Modulus or Division introduces SKEWed values and // will not give a uniform distribution (except for powers-of-two) public int getNoSkewInteger(int max) { int divisor = (int) (UInt32.MaxValue / (max + 1)); int newVal; do { newVal = (int)(extract_number() / divisor); } while (newVal > max); return newVal; } // Returns a random value in the range between // min and max values // Value may lose some of it's randomness with skewed // modulus value public int Next(int min, int max) { return (int) extract_number() % (max - min + 1) + min; } } }

Tl;dr - The Jamming Works Fine Mathematically*



So Far Nothing Appears modifies Jam except adding Mods to The Gun



NPC's follow the same rules for jamming as you do



The Random Generator in Unity is generally more resistant to repeating numbers then .NET or MT..

The formula is a simple unbiased comparison, they don't floor() the number or use division to generate a percentage which would introduce number

SKEW

Inb4 Matt comes in here and lectures me on Statistics