CrazyShooters2-InfiniteAmmo

Crazy shooters 2 Infinite ammo [hack]

// ==UserScript==
// @name         CrazyShooters2-InfiniteAmmo
// @namespace    nclib
// @version      0.1.1
// @description  Crazy shooters 2 Infinite ammo [hack]
// @author       nekocell
// @match        https://www.julgames.com/games/crazy-shooters-2/
// @grant        unsafeWindow
// ==/UserScript==

if (!('UnityLoader' in unsafeWindow)) {
  Object.defineProperty(unsafeWindow, 'UnityLoader', {
    enumerable: false,
    get() {
      return this._UnityLoader;
    },
    set(v) {
      this._UnityLoader = v;
      Object.defineProperty(this._UnityLoader, 'loadCode', {
        enumerable: false,
        get() {
          return new_loadCode;
        },
        set() {}
      })
    }
  })
} else {
  Object.defineProperty(unsafeWindow.UnityLoader, 'loadCode', {
    enumerable: false,
    get() {
      return new_loadCode;
    },
    set() {}
  })
}

class UnityAsmCodePatch {
  constructor(code) {
    this.code = code;
  }
  _getReFuncDef(funcName) {
    return new RegExp(`function ${funcName}\\(.*?\\){.*?return.*?}`);
  }
  PatchCodeInFunc(funcName, regex, newCode) {
    var reFunc = this._getReFuncDef(funcName);
    var func = this.code.match(reFunc)[0];
    func = func.replace(regex, newCode);
    this.code = this.code.replace(reFunc, func);
  }
  AddGlobalVariable(name, initVal) {
    this.code = this.code.replace(/\/\/ EMSCRIPTEN_START_FUNCS/, `var ${name}=${initVal};$&`);
  }
  AddFunc(funcCode) {
    this.code = this.code.replace(/\n\/\/ EMSCRIPTEN_END_FUNCS/, `${funcCode}$&`);
  }
  AddReturnFunc(keyname, name) {
    this.code = this.code.replace(/return{/, `$&${keyname}:${name},`);
  }
  NewCode() {
    return this.code;
  }
}

const new_loadCode = function(e, t, r) {
  console.log('Overrided loadCode');
  var code = (new TextDecoder).decode(e);
  var patch = null;

  switch (r.url) {
    case 'game.asm.code.unityweb':
      patch = new UnityAsmCodePatch(code);

      // infinite ammo
      patch.PatchCodeInFunc('vUn', /c\[b>>2\]=\(c\[b>>2\]\|0\)\+-1;/, 'if(!IsInfAmmo){$&}');
      patch.PatchCodeInFunc('VUn', /c\[x>>2\]=\(c\[x>>2\]\|0\)\+-1;/, 'if(!IsInfAmmo){$&}');
      patch.AddGlobalVariable('IsInfAmmo', '1');
      patch.AddFunc('function _SetIsInfAmmo(a){a=a|0;IsInfAmmo=a}');
      patch.AddReturnFunc('SetIsInfAmmo', '_SetIsInfAmmo');

      code = patch.NewCode();
      unsafeWindow.asm_code = code;
      break;
    case 'game.asm.framework.unityweb':
      code = code.replace(/var __GLOBAL__sub_I_runtime_utilities4_lump_cpp/, 'window.asm=asm;$&')
      break;
  }

  var n = r.url,
    o = document.createElement("script"),
    i = URL.createObjectURL(new Blob(['UnityLoader["' + n + '"]=', code], {
      type: "text/javascript"
    }));
  UnityLoader.Blobs[i] = r,
    o.src = i,
    o.onload = function() {
      URL.revokeObjectURL(i),
        t(n)
    },
    document.body.appendChild(o)
}