Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- let monsterhealth=150
- //modes are as follows:
- //0: standard, respecting custom values
- //1: shotgun
- //2: SSG
- //3: 40 BFG tracers
- //4: 40 BFG tracers + BFG ball
- //5: 1 BFG tracer
- let mode=0
- let rngmode=0 //0: vanilla rng; 1: boom rng; 2: perfect ideal distribution of rolls
- let cumprint=true //true if you want the final output to also print cumulative values
- let rollprint=true //true if you want the roll table to be printed at the end (normalised so the sum of all rolls is 100)
- let roundoutput=true //round output to 5 sigfig unless it would lose integer precision
- //ignored on modes >0
- //ex. 20 and 10 for punching, 5 and 3 for pistol
- let basedmg=20
- let range=8
- let consistentsplash = false //false if you want to use the range of 110-120 or whatever it is lol
- let splash=98 //splash damage, set to 0 if not using rockets - also minimum splash if consistentsplash=false
- let maxsplash=117 //max splash damage for range
- //keep in mind above 2 values are also used for rocket mode
- let rocketmode = true //rocket mode: get accurate range assuming enemy is walking towards you at "monsterspeed" units every "monsterrate" tics
- let monsterspeed = 10 //units moved per movement
- let monsterrate = 2 //tics per movement (1 will break my code just adjust the splash values and use the regular consistentsplash function for that)
- //don't touch this
- let t=Date.now()
- let dmg={0:1}
- let outp={}
- let PRNG = [0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66,
- 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36,
- 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188,
- 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224,
- 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242,
- 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0,
- 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235,
- 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113,
- 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75,
- 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196,
- 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113,
- 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241,
- 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224,
- 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95,
- 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226,
- 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36,
- 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106,
- 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136,
- 120, 163, 236, 249]
- //to obtain these tables I ignored the initial PRNG seed and simply ran every possible RNG value
- //due to the way RNG is initialised the first RNG call will always return an odd number, and then it alternates between even & odd on each call
- //every RNG value is still equally likely (occurs exactly 2 times) and the right-shift in the P_Random() function ensures this parity does not affect the actual RNG output
- let boomSSGTable = {
- "110": 176, "115": 2064, "120": 11376, "125": 51712, "130": 199328, "135": 652192, "140": 1880032, "145": 4845120,
- "150": 11218000, "155": 23614848, "160": 45180272, "165": 79390848, "170": 128525984, "175": 192190944, "180": 265873680, "185": 341163616, "190": 406654528, "195": 450420768,
- "200": 464287024, "205": 445193456, "210": 397141408, "215": 329356672, "220": 253760720, "225": 181330992, "230": 119820688, "235": 73163136, "240": 41187680, "245": 21205728,
- "250": 9948144, "255": 4273600, "260": 1639664, "265": 561552, "270": 168112, "275": 42448, "280": 9088, "285": 1440, "290": 240, "295": 16}
- let boomSGTable = {
- "35": 2073536, "40": 14340784, "45": 56911200, "50": 155151216, "55": 322040896, "60": 528369152, "65": 704610176, "70": 770981232,
- "75": 696387616, "80": 516129200, "85": 310947472, "90": 148070896, "95": 53655552, "100": 13387376, "105": 1910992
- }
- let boomBFGTable = {
- "2424": 512, "2425": 512, "2426": 1024, "2427": 512, "2429": 1024, "2430": 512, "2432": 512, "2433": 512, "2434": 1024, "2435": 512, "2436": 512, "2437": 512, "2438": 512,
- "2439": 1024, "2440": 1024, "2444": 2048, "2445": 1536, "2446": 1024, "2447": 2560, "2448": 2560, "2449": 512, "2450": 2048, "2451": 3072, "2452": 1024, "2453": 1024,
- "2454": 1536, "2455": 2048, "2456": 1024, "2457": 2048, "2458": 2048, "2459": 3584, "2460": 2048, "2461": 6144, "2462": 3584, "2463": 5120, "2464": 4096, "2465": 3584,
- "2466": 4096, "2467": 1536, "2468": 2560, "2469": 5120, "2470": 4096, "2471": 4608, "2472": 6656, "2473": 7168, "2474": 9728, "2475": 7168, "2476": 7680, "2477": 8192,
- "2478": 8704, "2479": 11776, "2480": 8192, "2481": 11776, "2482": 12800, "2483": 14848, "2484": 16384, "2485": 17408, "2486": 16896, "2487": 16896, "2488": 19456, "2489": 24064,
- "2490": 32256, "2491": 25600, "2492": 30208, "2493": 30208, "2494": 32768, "2495": 44032, "2496": 41984, "2497": 35328, "2498": 45568, "2499": 40448, "2500": 55296,
- "2501": 57344, "2502": 52224, "2503": 69120, "2504": 66560, "2505": 70656, "2506": 72704, "2507": 75776, "2508": 79872, "2509": 99328, "2510": 87552, "2511": 89088,
- "2512": 110080, "2513": 113152, "2514": 116224, "2515": 124928, "2516": 114176, "2517": 145920, "2518": 151552, "2519": 162304, "2520": 159232, "2521": 178176, "2522": 178176,
- "2523": 192512, "2524": 214016, "2525": 208896, "2526": 225792, "2527": 249856, "2528": 270336, "2529": 281600, "2530": 294912, "2531": 312832, "2532": 320000, "2533": 353792,
- "2534": 370176, "2535": 400896, "2536": 408576, "2537": 441344, "2538": 489472, "2539": 506880, "2540": 521728, "2541": 521728, "2542": 577536, "2543": 620544, "2544": 621056,
- "2545": 668160, "2546": 682496, "2547": 744448, "2548": 745472, "2549": 804864, "2550": 866304, "2551": 883712, "2552": 935424, "2553": 1009664, "2554": 1028096, "2555": 1052672,
- "2556": 1156096, "2557": 1189376, "2558": 1284608, "2559": 1367040, "2560": 1385984, "2561": 1436672, "2562": 1489920, "2563": 1567232, "2564": 1658880, "2565": 1742336,
- "2566": 1846784, "2567": 1867264, "2568": 1904640, "2569": 2065920, "2570": 2110976, "2571": 2196992, "2572": 2334208, "2573": 2420224, "2574": 2513920, "2575": 2610688,
- "2576": 2689024, "2577": 2847744, "2578": 2933248, "2579": 2958336, "2580": 3162624, "2581": 3279872, "2582": 3418112, "2583": 3598848, "2584": 3646464, "2585": 3813376,
- "2586": 3947520, "2587": 3986432, "2588": 4207104, "2589": 4381696, "2590": 4524032, "2591": 4719104, "2592": 4874752, "2593": 4991488, "2594": 5201920, "2595": 5430784,
- "2596": 5475328, "2597": 5699584, "2598": 6007808, "2599": 6183936, "2600": 6340096, "2601": 6579200, "2602": 6730240, "2603": 6887424, "2604": 7132160, "2605": 7310336,
- "2606": 7579648, "2607": 7803904, "2608": 8019456, "2609": 8277504, "2610": 8496640, "2611": 8752640, "2612": 9040384, "2613": 9338880, "2614": 9482240, "2615": 9814016,
- "2616": 10065408, "2617": 10273280, "2618": 10417152, "2619": 10839552, "2620": 11064832, "2621": 11408896, "2622": 11653120, "2623": 11939328, "2624": 12240384,
- "2625": 12516864, "2626": 12687360, "2627": 13039616, "2628": 13487616, "2629": 13663232, "2630": 14251008, "2631": 14319104, "2632": 14617600, "2633": 14903808,
- "2634": 15025664, "2635": 15385600, "2636": 15914496, "2637": 16132096, "2638": 16487936, "2639": 16854016, "2640": 17240576, "2641": 17546752, "2642": 17884160,
- "2643": 18251264, "2644": 18478592, "2645": 18871296, "2646": 19109376, "2647": 19536384, "2648": 19769344, "2649": 19960832, "2650": 20655616, "2651": 20644864,
- "2652": 21296640, "2653": 21296128, "2654": 21764096, "2655": 21972480, "2656": 22325248, "2657": 22724608, "2658": 22777344, "2659": 23212544, "2660": 23724544,
- "2661": 23855616, "2662": 24286720, "2663": 24343040, "2664": 24859648, "2665": 24974336, "2666": 25187840, "2667": 25572864, "2668": 26062336, "2669": 26275840,
- "2670": 26450432, "2671": 26634752, "2672": 27142144, "2673": 27262464, "2674": 27417088, "2675": 27637248, "2676": 27896832, "2677": 27995136, "2678": 27977728,
- "2679": 28504576, "2680": 28476928, "2681": 28703232, "2682": 28879360, "2683": 29074944, "2684": 29399552, "2685": 29598208, "2686": 29593088, "2687": 29704704,
- "2688": 29877248, "2689": 30120448, "2690": 29886976, "2691": 29805056, "2692": 30177280, "2693": 30393856, "2694": 30406144, "2695": 30354432, "2696": 30529024,
- "2697": 30382592, "2698": 30438400, "2699": 30469632, "2700": 30327808, "2701": 30467584, "2702": 30281216, "2703": 30386688, "2704": 30402048, "2705": 30545920,
- "2706": 30337024, "2707": 30216704, "2708": 30140416, "2709": 30234112, "2710": 29915648, "2711": 29591552, "2712": 29582336, "2713": 29927936, "2714": 29413888,
- "2715": 29496832, "2716": 29313536, "2717": 29304832, "2718": 28797952, "2719": 28536320, "2720": 28594176, "2721": 28642304, "2722": 28003328, "2723": 27817472,
- "2724": 27913728, "2725": 27444736, "2726": 27698688, "2727": 27238912, "2728": 26849792, "2729": 26727936, "2730": 26294272, "2731": 26219008, "2732": 25915904,
- "2733": 25805312, "2734": 25320448, "2735": 25065984, "2736": 24713216, "2737": 24619520, "2738": 24032256, "2739": 23987200, "2740": 23721472, "2741": 23299072,
- "2742": 23172608, "2743": 22827520, "2744": 22464000, "2745": 22239232, "2746": 21722112, "2747": 21357568, "2748": 21308416, "2749": 20881920, "2750": 20679680,
- "2751": 20465152, "2752": 20111360, "2753": 19546624, "2754": 19423232, "2755": 18901504, "2756": 18633728, "2757": 18236928, "2758": 17902592, "2759": 17644032,
- "2760": 17439232, "2761": 17047040, "2762": 16723456, "2763": 16229376, "2764": 15942656, "2765": 15698944, "2766": 15347200, "2767": 15187968, "2768": 14638592,
- "2769": 14430720, "2770": 14025216, "2771": 13698560, "2772": 13553664, "2773": 13282816, "2774": 12925952, "2775": 12552704, "2776": 12151808, "2777": 11855872,
- "2778": 11570688, "2779": 11356672, "2780": 11085824, "2781": 10804224, "2782": 10598912, "2783": 10215936, "2784": 10223616, "2785": 9739776, "2786": 9531904, "2787": 9210880,
- "2788": 8980480, "2789": 8622080, "2790": 8477184, "2791": 8295936, "2792": 8024064, "2793": 7700992, "2794": 7607296, "2795": 7267840, "2796": 7049216, "2797": 6899200,
- "2798": 6696448, "2799": 6489600, "2800": 6222336, "2801": 6163456, "2802": 5800448, "2803": 5717504, "2804": 5500416, "2805": 5327360, "2806": 5166080, "2807": 5027840,
- "2808": 4759552, "2809": 4653568, "2810": 4371968, "2811": 4321792, "2812": 4168192, "2813": 4060672, "2814": 3929088, "2815": 3723776, "2816": 3572224, "2817": 3402752,
- "2818": 3384320, "2819": 3228672, "2820": 3206656, "2821": 2969600, "2822": 2973184, "2823": 2816000, "2824": 2666496, "2825": 2620928, "2826": 2444800, "2827": 2257920,
- "2828": 2290688, "2829": 2175488, "2830": 2101760, "2831": 2023936, "2832": 1903616, "2833": 1852928, "2834": 1767936, "2835": 1691648, "2836": 1665536, "2837": 1523712,
- "2838": 1478144, "2839": 1421824, "2840": 1389056, "2841": 1293312, "2842": 1266688, "2843": 1233408, "2844": 1144320, "2845": 1081856, "2846": 1032192, "2847": 1008640,
- "2848": 978944, "2849": 884224, "2850": 830976, "2851": 785408, "2852": 765952, "2853": 769024, "2854": 692736, "2855": 689664, "2856": 630784, "2857": 625152, "2858": 601088,
- "2859": 553984, "2860": 538624, "2861": 498688, "2862": 473088, "2863": 433152, "2864": 436224, "2865": 390656, "2866": 377856, "2867": 363008, "2868": 335360, "2869": 324608,
- "2870": 299008, "2871": 282112, "2872": 260096, "2873": 264704, "2874": 227840, "2875": 212992, "2876": 215040, "2877": 202240, "2878": 179712, "2879": 169984, "2880": 168448,
- "2881": 167936, "2882": 147968, "2883": 123904, "2884": 118784, "2885": 130560, "2886": 120320, "2887": 102912, "2888": 102400, "2889": 82432, "2890": 88064, "2891": 76800,
- "2892": 74240, "2893": 69120, "2894": 76288, "2895": 67584, "2896": 58880, "2897": 45056, "2898": 48128, "2899": 49664, "2900": 45568, "2901": 44032, "2902": 41984,
- "2903": 35328, "2904": 34304, "2905": 31744, "2906": 25600, "2907": 31232, "2908": 22016, "2909": 20992, "2910": 23552, "2911": 20480, "2912": 15360, "2913": 15872,
- "2914": 14848, "2915": 11776, "2916": 13312, "2917": 16896, "2918": 10752, "2919": 13824, "2920": 8704, "2921": 8704, "2922": 6656, "2923": 6144, "2924": 6656, "2925": 4096,
- "2926": 3072, "2927": 7680, "2928": 2560, "2929": 7168, "2930": 3072, "2931": 5632, "2932": 5120, "2933": 4096, "2934": 1024, "2935": 5120, "2936": 6144, "2937": 1536,
- "2938": 1536, "2939": 2048, "2940": 2048, "2941": 2048, "2942": 2048, "2943": 3584, "2944": 1536, "2945": 3584, "2946": 512, "2947": 2048, "2948": 2560, "2949": 2048,
- "2950": 1024, "2951": 2048, "2952": 1024, "2953": 2048, "2955": 1024, "2956": 1536, "2957": 512, "2958": 2560, "2959": 1536, "2960": 1024, "2961": 1024, "2962": 1536,
- "2963": 512, "2964": 512, "2966": 512, "2967": 512, "2973": 512, "2974": 512, "2976": 512
- }
- let boomTracerTable = {"26": 1024, "27": 2560, "28": 3584, "29": 5120, "30": 10240, "31": 20480, "32": 22528, "33": 61952, "34": 76800, "35": 152576, "36": 243712, "37": 387584,
- "38": 577024, "39": 922624, "40": 1404928, "41": 2021376, "42": 2871296, "43": 4070912, "44": 5553664, "45": 7546368, "46": 10203648, "47": 13490688, "48": 17437184,
- "49": 22211072, "50": 28212224, "51": 34910208, "52": 43022336, "53": 52021248, "54": 61858816, "55": 72724480, "56": 84642304, "57": 96925184, "58": 109870080, "59": 122261504,
- "60": 135552000, "61": 147715072, "62": 158703104, "63": 169087488, "64": 177570304, "65": 183586304, "66": 188894208, "67": 191238656, "68": 190485504, "69": 188260864,
- "70": 183988736, "71": 177042944, "72": 168504832, "73": 159318528, "74": 147393024, "75": 135540736, "76": 122732032, "77": 109907456, "78": 97223168, "79": 84743680,
- "80": 72975360, "81": 61939200, "82": 51587584, "83": 42720768, "84": 35087872, "85": 28123136, "86": 22316032, "87": 17399808, "88": 13352448, "89": 10170368, "90": 7585280,
- "91": 5694464, "92": 4035072, "93": 2814976, "94": 1938944, "95": 1408512, "96": 942592, "97": 624640, "98": 373248, "99": 274432, "100": 154112, "101": 87040, "102": 50176,
- "103": 29696, "104": 18432, "105": 12288, "106": 6144, "107": 4096, "108": 1024, "109": 2048, "110": 1024, "111": 512
- }
- let rngindex=0;
- function M_Random(){
- rngindex=(rngindex+1)%256
- return PRNG[rngindex]
- }
- function normalise(obj){ //weighted so a perfect range would be all 1s, for the sake of multiplying out probabilities later - sum equals the length of the table
- let objk=Object.keys(obj)
- let sum=0
- for(let i=0;i<objk.length;i++){
- sum+=obj[objk[i]]
- }
- for(let i=0;i<objk.length;i++){
- obj[objk[i]]/=sum/objk.length
- //for the sake of sanity
- if(obj[objk[i]]==0){
- delete obj[objk[i]]
- }
- }
- return obj
- }
- function calc40Tracers(){
- if(rngmode==0){ //vanilla
- for(i=0;i<=255;i++){
- rngindex=i;
- let sum=0;
- //rng calls per tracer are as follows:
- //1: P_SpawnMobj rolls for random player target
- //16: 15 rolls(!!!) for damage sum - 1-8 dmg per roll
- //enemy is damaged
- //if the enemy dies: 1 extra call for tic delay on death animation, another call if it is 64 units above you & dmg is under 40???? does RNG get called if the checks fail?
- //if the enemy dies: P_DamageMobj RETURNS now
- //if the enemy survives:
- //17: P_DamageMobj rolls for pain chance
- for(j=0;j<40;j++){
- M_Random()
- let tsum=0;
- for(k=0;k<15;k++){
- tsum+=(M_Random()%8)+1
- }
- sum+=tsum
- M_Random()
- }
- rolls[sum] = (rolls[sum] ?? 0) + 1
- }
- }else if(rngmode==1){//boom
- //just pre-bake all tracer rolls
- rolls=normalise(boomBFGTable)
- }else{//ideal
- let tracerRolls={0:1}
- for(i=0;i<15;i++){
- let newdmg={}
- let rolkeys=Object.keys(tracerRolls);
- for(l=0;l<rolkeys.length;l++){
- for(j=1;j<=8;j++){
- let df=j+Number(rolkeys[l])
- newdmg[df] = (newdmg[df]??0)+tracerRolls[rolkeys[l]]
- }
- }
- tracerRolls=newdmg
- }
- normalise(tracerRolls)
- let trollkeys = Object.keys(tracerRolls)
- let bfgrolls={0:1}
- for(i=0;i<40;i++){
- let newdmg={}
- let rolkeys=Object.keys(bfgrolls)
- for(l=0;l<rolkeys.length;l++){
- for(j=0;j<trollkeys.length;j++){
- let dfds = Number(rolkeys[l])+Number(trollkeys[j])
- newdmg[dfds] = (newdmg[dfds]??0) + (bfgrolls[rolkeys[l]]*tracerRolls[trollkeys[j]])
- }
- }
- bfgrolls=newdmg
- }
- normalise(bfgrolls)
- rolls=bfgrolls
- }
- }
- let rolls = {}
- switch (mode){
- case 0:
- if(rngmode==0){ //vanilla - build table of expected chances of damage values (weighted so a perfect range would be all 1s)
- for(i=0;i<PRNG.length;i++){
- let roll = ((PRNG[i]%range)+1)*basedmg+splash
- rolls[roll] = (rolls[roll]??0)+/*(range/256)*/range
- }
- }else if(rngmode==1){//boom
- for(i=0;i<256;i++){ //just iterate 1-256 to match boom expected output
- let roll = ((i%range)+1)*basedmg+splash
- rolls[roll] = (rolls[roll]??0)+/*(range/256)*/range
- }
- }else{ //assume perfect range
- for(let j=basedmg+splash;j<=(basedmg*range)+splash;j+=basedmg){
- rolls[j]=1
- }
- }
- if(rocketmode){
- //first pass under normal conditions...
- let splashdiff = maxsplash-splash
- let newdmg={}
- let rolkeys=Object.keys(rolls)
- console.log(rolls)
- for(j=0;j<rolkeys.length;j++){
- for(k=0;k<=splashdiff;k++){
- let df=Number(rolkeys[j])+k
- newdmg[df] = (newdmg[df]??0)+rolls[rolkeys[j]]
- }
- }
- //now another pass with extra damage from the enemy walking into the rocket
- let cappeddmg = 128-splash
- for(j=0;j<rolkeys.length;j++){
- for(k=0;k<=splashdiff;k++){
- let df=Number(rolkeys[j])+Math.min(k+monsterspeed,cappeddmg)
- newdmg[df] = (newdmg[df]??0)+(rolls[rolkeys[j]]/(monsterrate-1))
- }
- }
- console.log(newdmg)
- rolls=newdmg
- }else{
- if(!consistentsplash){ //splash damage range - iterate through and spread out odds evenly across range
- let splashdiff = maxsplash-splash
- let newdmg={}
- let rolkeys=Object.keys(rolls)
- console.log(rolls)
- for(j=0;j<rolkeys.length;j++){
- for(k=0;k<=splashdiff;k++){
- let df=k+Number(rolkeys[j])
- newdmg[df] = (newdmg[df]??0)+rolls[rolkeys[j]]
- }
- }
- console.log(newdmg)
- rolls=newdmg
- }
- }
- break;
- case 1: //shotgun
- if(rngmode==0){ //vanilla
- for(i=0;i<=255;i++){
- rngindex=i;
- let sum=0;
- //rng calls are as follows (i think???):
- //1: P_GunShot rolls for damage
- //3: P_GunShot rolls twice for horizontal offset
- //5: P_SpawnBlood rolls twice for Z offset
- //6: P_SpawnMobj might roll when blood is spawned? to pick a random player target?
- //7: P_SpawnBlood rolls for animation tic delay
- //enemy is damaged
- //if the enemy dies: 1 extra call for tic delay on death animation, another call if it is 64 units above you & dmg is under 40????
- // * -- does RNG get called if the height and damage checks fail?? sometimes this extra RNG call doesn't happen after a death?
- //if the enemy dies: P_DamageMobj RETURNS now
- //if the enemy survives:
- //8: P_DamageMobj rolls for pain chance
- for(j=0;j<7;j++){
- sum+=((M_Random()%3)+1)*5
- for(d=0;d<7;d++){M_Random()}
- }
- rolls[sum] = (rolls[sum] ?? 0) + 1
- }
- }else if(rngmode==1){
- //just use pre-baked SG roll table
- rolls = boomSGTable
- }else{//ideal
- let sgrolls={0:1}
- for(i=0;i<7;i++){
- let newdmg={}
- let rolkeys=Object.keys(sgrolls)
- for(j=0;j<rolkeys.length;j++){
- for(k=5;k<=15;k+=5){
- let df=k+Number(rolkeys[j])
- newdmg[df] = (newdmg[df]??0)+sgrolls[rolkeys[j]]
- }
- }
- console.log(newdmg)
- sgrolls=newdmg
- }
- rolls=sgrolls
- }
- break;
- case 2: //SSG
- if(rngmode==0){//vanilla
- for(i=0;i<=255;i++){
- rngindex=i;
- let sum=0;
- //rng calls are as follows (i think???):
- //1: A_FireShotgun2 rolls for damage
- //3: A_FireShotgun2 rolls twice for horizontal offset
- //5: A_FireShotgun2 rolls twice for vertical offset
- //7: P_SpawnBlood rolls twice for Z offset
- //8: P_SpawnMobj might roll when blood is spawned? to pick a random player target?
- //9: P_SpawnBlood rolls for animation tic delay
- //enemy is damaged
- //if the enemy dies: 1 extra call for tic delay on death animation, another call if it is 64 units above you & dmg is under 40????
- // * -- does RNG get called if the checks fail?
- //if the enemy dies: P_DamageMobj RETURNS now
- //if the enemy survives:
- //10: P_DamageMobj rolls for pain chance
- for(j=0;j<20;j++){
- sum+=((M_Random()%3)+1)*5
- for(d=0;d<9;d++){M_Random()}
- }
- rolls[sum] = (rolls[sum] ?? 0) + 1
- }
- }else if(rngmode==1){//boom
- rolls=boomSSGTable
- }else{
- let sgrolls={0:1}
- for(i=0;i<20;i++){
- let newdmg={}
- let rolkeys=Object.keys(sgrolls)
- for(j=0;j<rolkeys.length;j++){
- for(k=5;k<=15;k+=5){
- let df=k+Number(rolkeys[j])
- newdmg[df] = (newdmg[df]??0)+sgrolls[rolkeys[j]]
- }
- }
- console.log(newdmg)
- sgrolls=newdmg
- }
- rolls=sgrolls
- }
- break;
- case 3:
- calc40Tracers()
- break;
- case 4:
- calc40Tracers()
- console.log(rolls)
- //now do 100-800 from the ball on top of the table
- if(rngmode==0){//vanilla
- let newrolls={}
- let brollkeys=Object.keys(rolls)
- for(j=0;j<brollkeys.length;j++){
- for(i=0;i<PRNG.length;i++){
- let roll = Number(brollkeys[j]) + (((PRNG[i]%8)+1)*100)
- newrolls[roll] = (newrolls[roll]??0)+rolls[brollkeys[j]]
- }
- }
- rolls=newrolls
- }else{//boom matches ideal distribution here so can use the same code
- let newrolls={}
- let brollkeys=Object.keys(rolls)
- for(j=0;j<brollkeys.length;j++){
- for(i=100;i<=800;i+=100){
- let roll = Number(brollkeys[j]) + i
- newrolls[roll] = (newrolls[roll]??0)+rolls[brollkeys[j]]
- }
- }
- rolls=newrolls
- }
- break;
- case 5:
- if(rngmode==0){//vanilla
- for(i=0;i<=255;i++){
- rngindex=i;
- let sum=0;
- for(k=0;k<15;k++){
- sum+=(M_Random()%8)+1
- }
- rolls[sum] = (rolls[sum] ?? 0) + 1
- }
- }else if(rngmode==1){//boom
- //just use pre-baked tracer roll table
- rolls = boomTracerTable
- }else{//ideal
- let tracerRolls={0:1}
- for(i=0;i<15;i++){
- let newdmg={}
- let rolkeys=Object.keys(tracerRolls);
- for(l=0;l<rolkeys.length;l++){
- for(j=1;j<=8;j++){
- let df=j+Number(rolkeys[l])
- newdmg[df] = (newdmg[df]??0)+tracerRolls[rolkeys[l]]
- }
- }
- tracerRolls=newdmg
- }
- rolls=tracerRolls
- }
- break;
- }
- console.log(JSON.stringify(rolls))
- normalise(rolls)
- console.log("Roll table:\n---")
- console.log(rolls)
- console.log("---")
- let rollkeys=Object.keys(rolls)
- //repeatedly apply roll table over itself and record probabilities
- //TODO: support e3m8 style mixed damage cases, like 3 rockets + indeterminate cells against a mastermind
- //maybe this could all use bigints to avoid loss of precision, or some other format like tracking quotients as fractions
- for(hit=1;hit<Math.ceil(monsterhealth/(rollkeys[0]))+1;hit++){
- let newdmg={}
- let dmgkeys=Object.keys(dmg)
- for(i=0;i<dmgkeys.length;i++){
- for(let j=0;j<rollkeys.length;j++){
- let dfds=Number(rollkeys[j])+Number(dmgkeys[i])
- newdmg[dfds] = (newdmg[dfds] ?? 0) + (dmg[dmgkeys[i]]*rolls[rollkeys[j]])/rollkeys.length
- }
- }
- //check if any rolls result in death
- let ndmgkeys=Object.keys(newdmg)
- let totdead=0
- for(i=0;i<ndmgkeys.length;i++){
- if(ndmgkeys[i]>=monsterhealth){
- totdead+=newdmg[ndmgkeys[i]]
- delete newdmg[ndmgkeys[i]]
- }
- }
- if(totdead>0){outp[hit]=(100*totdead)} // /(rollkeys.length**hit)}
- dmg=newdmg
- }
- function sround(x, n=5){
- //rounds to n sig figs unless it would lose integer precision
- if(x<10**n){
- return parseFloat(x.toPrecision(n))
- }else{
- return Math.round(x)
- }
- }
- if(rollprint){
- let sum=0
- let avgsum=0
- for(let i=0;i<rollkeys.length;i++){
- sum+=rolls[rollkeys[i]]
- avgsum+=(rolls[rollkeys[i]]*rollkeys[i])
- }
- console.log("Average damage: "+avgsum/rollkeys.length)
- for(let i=0;i<rollkeys.length;i++){
- rolls[rollkeys[i]]/=sum/100
- }
- console.log(rollprint)
- let cum=0
- let str="Damage Chance (%) Cumulative Expected"
- for(i=0;i<rollkeys.length;i++){
- cum+=rolls[rollkeys[i]]
- if(roundoutput){
- str=str+"\n"+rollkeys[i]+" "+sround(rolls[rollkeys[i]])+" "+sround(cum)+" "+sround(100/cum)
- }else{
- str=str+"\n"+rollkeys[i]+" "+rolls[rollkeys[i]]+" "+cum+" "+(100/cum)
- }
- }
- console.log(str)
- }
- let avgsum=0
- for(let i=0;i<Object.keys(outp).length;i++){
- let x=Object.keys(outp)[i]
- avgsum+=(Number(x)*outp[x])
- }
- console.log("Average hits: "+avgsum/100)
- //print it to easily paste into excel
- let str="Shots Chance"
- if(cumprint){str="Shots Chance (%) Cumulative Expected"}
- let cum=0
- for(i=0;i<Object.keys(outp).length;i++){
- let x=Object.keys(outp)[i]
- cum+=outp[x]
- if(roundoutput){
- str=str+"\n"+x+" "+sround(outp[x])
- if(cumprint){str=str+" "+sround(cum)+" "+sround(100/cum)}
- }else{
- str=str+"\n"+x+" "+outp[x]
- if(cumprint){str=str+" "+cum+" "+(100/cum)}
- }
- }
- console.log(str)
- console.log("Run in "+(Date.now()-t)+"ms")
Add Comment
Please, Sign In to add comment