Immortal
Arcane
The funny thing is that we could never prove the numbers are lying, unless we looked at the code...
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;
}
Checks if your weapon is a long range weapon.. if so it runs the algorithm to see if you will be jammed for this attack.
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;
}
This is the code that generates the actual ChanceToJam Percentage.. it's based off a weapon template and any mods you added to the weapon. No other factors *APPEAR* to matter.
Only the base % of the weapon to Jam and any mods that may increase or decrease chance to Jam.
Code:
public bool CheckForJammed()
{
int chanceToJam = this.GetChanceToJam();
int num = Random.Range(0, 100);
if (num < chanceToJam)
{
this.SetJammed(true);
return true;
}
return false;
}
This is the actual algorithm code that people think is broken.. Here We Go..
Essentially
int chanceToJam = this.GetChanceToJam();
Take the chance % for a weapon to Jam then generate a random number between 1 and 100... if that number is below the percentage then your weapon Jams..
Curious about the Random number generator?
Unity uses the Marsaglia's Xorshift 128 Algorithm - http://en.wikipedia.org/wiki/Xorshift
"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)"
This random generator out performs Mersenne Twister when put up against the BC Suite.. which is on equal par with the .NET random generator implemented by Microsoft (Donald E. Knuth's subtractive random number generator algorithm)
Here are the results of a program I wrote for my Statistical Theory Course comparing MT with Donald's Subtractive algorithm (Again the one employed by .NET)
Source Code for my implementation of MT (If you want to test this algorithm next to .NET or Unity)
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
* True Random Doesn't Exist But It's as close as your gonna get
Warning: I spent about 10 minutes looking at the code and writing this response.. I will keep looking it over and if I missed something then I will update the thread, or if one of the other 1337 hax0rs wants to contest my thread then please go ahead.
Last edited: