cleolibrary / CLEO-Redux

Experimental JavaScript runtime for GTA 3D era games/GTA IV/Bully
https://re.cleo.li
Other
213 stars 20 forks source link

Pools and callbacks #28

Closed borsuczyna closed 1 year ago

borsuczyna commented 2 years ago

Pools are most Important thing to make good mod tool, really hope for them, example:

CPool.GetVehiclesPool().forEach(function(element, index) { 
    element.explode();
});

Also I really hope replacing existing GTA callbacks, that game will call intead of default ones, for example replacing add wanted level callback:

Memory.AttachToCallback(0x000000, function() {
     log("game tried to change wanted level");
});

Greetings! #

x87 commented 2 years ago

as I mentioned on Discord you can iterate pool using existing Memory command (not in DE for now).

Example script creating blips over police cars in GTA 3 1.0


/// <reference path=".config/gta3.d.ts" />

// wrapper over CPool class providing common interface for storing dynamically created entities (ped, vehicles, objects, etc)
function Pool(addr, entitySize) {
    this.addr = addr;
    this.entities = Memory.ReadU32(addr + 0, false);
    this.flags = Memory.ReadU32(addr + 4, false);
    this.size = Memory.ReadI32(addr + 8, false);
    this.entitySize = entitySize;
  }
  Pool.prototype = {
    getFlag: function (index) {
      return Memory.ReadU8(this.flags + index, false);
    },
    getIndex: function (struct) {
      return (struct - this.entities) / this.entitySize;
    },
    isFree: function (index) {
      return this.getFlag(index) & 0x80;
    },
    getHandle: function (struct) {
      var index = this.getIndex(struct);
      return (index << 8) + this.getFlag(index);
    },
    getEntity: function (index) {
      return this.entities + index * this.entitySize;
    },
    getEntities: function () {
      var result = [];
      for (var i = 0; i < this.size; i++) {
        if (!this.isFree(i)) {
          result.push(this.getEntity(i));
        }
      }
      return result;
    },
  };

  var BLIPS = 0x006ed5e0;
  var MI_POLICE = 116;

  function findThisEntityBlip(handle) {
    var COUNT = 32;
    var SIZE = 0x30;
    for (var i = 0; i < COUNT; i++) {
      var inUse = Memory.ReadU8(BLIPS + i * SIZE + 0x23, false);
      if (inUse) {
        var h = Memory.ReadU32(BLIPS + i * SIZE + 0x8, false);
        if (handle == h) {
          var blipIndex = Memory.ReadU16(BLIPS + i * SIZE + 0x20, false);
          ///  blipArrId | (CRadar::ms_RadarTrace[_index].m_nBlipIndex << 16);
          return i | (blipIndex << 16);
          // return blipIndex;
        }
      }
    }
  }

  if (GAME !== "gta3") {
    log("Sorry, this script is for GTA III only");
  } else {
    // create a function to get the vehicle pool address
    var GetVehiclePool = Memory.Fn.CdeclU32(0x00545300);

    // create a wrapper over the vehicle pool object
    var vehPool = new Pool(GetVehiclePool(), 0x5a8);

    while (true) {
      wait(500);
      // iterate over all created vehicles
      vehPool.getEntities().forEach(function (vehicle) {
        // create a new instance of a script vehicle
        var handle = vehPool.getHandle(vehicle);
        var v = new Car(handle);

        // v now can be used with script commands defined for Vehicle class
        // check that v is a police car with a driver and it has no blip yet
        if (
          !Car.IsDead(v) &&
          v.getModel() === MI_POLICE &&
          !Char.IsDead(v.getDriver()) &&
          !findThisEntityBlip(handle)
        ) {
          Blip.AddForCarOld(v, 2, 2);
        }
      });
    }
  }```
x87 commented 2 years ago

Idea to create callbacks/hooks was briefly discussed here https://github.com/cleolibrary/CLEO-Redux/discussions/1#discussioncomment-1217851

x87 commented 2 years ago

some ideas:

addEventListener("onMount", () => { log("script has been reloaded") })
addEventListener("onUnMount", () => { log("script is about to be unloaded") })
x87 commented 1 year ago

WIP

addEventListener("OnVehicleCreate", ({ data }) => {
  let { address } = data;
  let handle = vehPool.getHandle(address);
  let c = new Car(handle);
  if (c.isModel(POLICE_MI)) {
    Blip.AddForCarOld(c, 2, BlipDisplay.BlipOnly);
  }
});

https://media.discordapp.net/attachments/914958450667175977/1053787400855359508/image.png

x87 commented 1 year ago

Pools are available in scm.ts library https://github.com/x87/scm.ts

Events are supported since 1.0.6 https://re.cleo.li/docs/en/events.html