Author Topic: LUA: Iterating through object instances in main loop at runtime?  (Read 376 times)

Offline JT

  • Zombie Food
  • *
  • Posts: 5
    • View Profile
I'd like to introduce a "capacitor" vehicle part in my mod, which is essentially just a "leaky" battery even at 100% condition which won't leak while being charged, but I can't see any means of accessing items at runtime.

Is it possible to iterate through vehicles or vehicle parts at runtime using Lua?  In the end I probably don't even need any bindings to vehicles' parts directly, provided the frames, vehicle parts, etc. are tracked as "items" in the world, but I haven't seen any mod example of a .lua iterator that scans through nearby objects at runtime, nor have I seen any poll/heartbeat-based (rather than event-based, i.e., "iuse") Lua scripts.  Almost all examples of Lua scripting I've seen generally revolve around simply modifying the creature templates once in their main.lua.

If I were to define a loop in a .lua script and then poll the game timer to see if the game time has changed, would that be the means by which I could do this, or is Lua given full control over the game loop without pausing (i.e., will freeze game due to infinite loop)?

The pseudocode is the barest-bones:

define leaky_item_id_list: { "classname", "classname2", ... }

every X in-game ticks:
   foreach item in bubble
      if item.id is in leaky_item_id_list
         if item.ammo_capacity > 0 and item.ammo_current > 0
            item.ammo_current = item.ammo_current - 1

Offline Zhilkin

  • NPC
  • **
  • Posts: 134
    • View Profile
Re: LUA: Iterating through object instances in main loop at runtime?
« Reply #1 on: May 28, 2017, 10:05:45 AM »
vehicle related classes aren't exported to LUA

Offline JT

  • Zombie Food
  • *
  • Posts: 5
    • View Profile
Re: LUA: Iterating through object instances in main loop at runtime?
« Reply #2 on: May 29, 2017, 07:55:18 AM »
In the end I probably don't even need any bindings to vehicles' parts directly, provided the frames, vehicle parts, etc. are tracked as "items" in the world,
vehicle related classes aren't exported to LUA

This should still be doable because fuel and battery power (and consumable liquids) are tracked as "ammo" in "item" classes, as I understand it.  I wouldn't mind Lua bindings for vehicles but it doesn't seem necessary if you can match based on ID.

The meat of my request has nothing to do with vehicles, though, but rather whether it's possible to execute code in the game on a heartbeat or with a periodic callback timer, and therefrom get an iterable list of objects at runtime to scan through and do magic to. =)

Offline Kevin Granade

  • Administrator
  • Survivor
  • *****
  • Posts: 5447
  • I code dead people.
    • View Profile
Re: LUA: Iterating through object instances in main loop at runtime?
« Reply #3 on: May 29, 2017, 09:11:33 AM »
What you're trying to do here would be absurdly easier in native code, is there a particular reason you're trying to do this in pure LUA?
Its like a fun family cookout, except your family is burning in flames while trying to eat you. -secretfire
I'm more excited than a survivor on meth and toast'ems. -Nighthawk
The the giant wasp is slammed through the zombie brute!

Offline Zhilkin

  • NPC
  • **
  • Posts: 134
    • View Profile
Re: LUA: Iterating through object instances in main loop at runtime?
« Reply #4 on: May 29, 2017, 10:09:38 PM »
In the end I probably don't even need any bindings to vehicles' parts directly, provided the frames, vehicle parts, etc. are tracked as "items" in the world,
vehicle related classes aren't exported to LUA

This should still be doable because fuel and battery power (and consumable liquids) are tracked as "ammo" in "item" classes, as I understand it.  I wouldn't mind Lua bindings for vehicles but it doesn't seem necessary if you can match based on ID.

The meat of my request has nothing to do with vehicles, though, but rather whether it's possible to execute code in the game on a heartbeat or with a periodic callback timer, and therefrom get an iterable list of objects at runtime to scan through and do magic to. =)
Items are contained in inventory and on the map. It should be possible to iterate through player inventory and also thorugh items on the map.

Vehicle parts installed on the vehicle are not items - you cannot iterate through them. Also I dunno if it is possible to iterate through items in containers.

Lua functions are the following:

local items_map = game.items_at(x, y) --table will contain all items at x, y coordinates on the map
local item_inventory = player:i_at(0) --will containe first item in player inventory (positive numbers are inventory items, negative numbers are equipped items)

You would also like to check if inventory items are finished to stop processing, like this:

player:i_at(-2):display_name() ~= "none"

Also there are two LUA callbacks on_day_passed and on_minute_passed (see https://github.com/CleverRaven/Cataclysm-DDA/blob/master/src/game.cpp#L1415-L1424) - you would likely want to use the latter.
« Last Edit: May 29, 2017, 10:48:24 PM by Zhilkin »

Offline Zhilkin

  • NPC
  • **
  • Posts: 134
    • View Profile
Re: LUA: Iterating through object instances in main loop at runtime?
« Reply #5 on: May 30, 2017, 04:23:34 PM »
1. Download archive https://www.dropbox.com/s/5vllfpns12i4gm3/LuaSandbox.zip?dl=0.
2. Unpack to mods folder.
3. Change absolute path to `LuaSandbox_test.lua`, `LuaSandbox_test2.lua` and `LuaSandbox_item_scanner.lua` files in `preload.lua`, so it will actually lead to the files in mods folder.

Code: [Select]
function iuse_luasandbox_test(item, active)

dofile ("C:\\Utils\\cdda\\data\\mods\\LuaSandbox\\LuaSandbox_test.lua")

end

function iuse_luasandbox_test2(item, active)

dofile ("C:\\Utils\\cdda\\data\\mods\\LuaSandbox\\LuaSandbox_test2.lua")

end

function iuse_luasandbox_item_scanner(item, active)

dofile ("C:\\Utils\\cdda\\data\\mods\\LuaSandbox\\LuaSandbox_item_scanner.lua")

end
game.register_iuse("IUSE_LUA_LUASANDBOX_TEST", iuse_luasandbox_test)
game.register_iuse("IUSE_LUA_LUASANDBOX_TEST2", iuse_luasandbox_test2)
game.register_iuse("IUSE_LUA_LUASANDBOX_ITEM_SCANNER", iuse_luasandbox_item_scanner)

4. Start game in new world with `LuaSandbox` mod enabled.
5. Go to debug menu and add `luasandbox_tester`, `luasandbox_tester2` and `luasandbox_item_scanner` items to your character.

6. Activate `luasandbox_tester` item to scan reality bubble and display menu with names, weights, volumes and coordinates of all items located in reality bubble. Selecting menu entry will teleport you on map to location of selected item.

7. Activate `luasandbox_tester2` item to scan player character inventory and display menu with names, weights, volumes and inventory position of all items located in player character inventory. Selecting menu entry will display popup with name of selected item.

8. Activate `luasandbox_item_scanner` to scan a part of reality bubble and display menu with names, weights, volumes and coordinates of all items located in reality bubble. Selecting menu entry will highlight selected items on map with `fd_laser`. It is also possible to highlight all found items. You can change values for `search mask` (LUA wildcards), `scan range` (better not try more than REALITY_BUBBLE/2=66) and `highlight` (fd_laser, fd_smoke, fd_fire, etc) in the options sub-menu.

N.B.:
Strangely, liquids contained in vehicle tanks (like gasoline and diesel) are counted as items located on the map.
« Last Edit: May 31, 2017, 10:05:22 AM by Zhilkin »

Offline JT

  • Zombie Food
  • *
  • Posts: 5
    • View Profile
Re: LUA: Iterating through object instances in main loop at runtime?
« Reply #6 on: May 31, 2017, 03:30:48 AM »
Thanks for all the pointers, Zhilkin!  I'll probe around with this and see where it takes me.


What you're trying to do here would be absurdly easier in native code, is there a particular reason you're trying to do this in pure LUA?

I'm not really a programmer.  I self-style myself as a "designer" but even that'd be considered a joke since it's usually all bluster and no substance.  Thus, while I do know a fair bit of "real" programming, I'm a scripter at heart.

In other words, the reason is mostly the difficulty on running exclusively on Windows versus a Linux-based development environment, and the need to download and run Git externally to actually synch my fork to the core repo (the web interface doesn't support upstreams), paired with the phenomenal difficulty I had in trying to get a Visual Studio setup compiling.  I did an hour of finagling before I decided the work needed exceeded my interest/attention span.  Setting up a development environment and dependencies and dealing with the idiosyncrasies of the code is always such a massive chore compared to just having a scripting environment with an API where I know everything already works out of the box and is either "possible" or "impossible".  Anyway, there are other advantages to a purely modded solution -- being able to stick to pure scripting gives me code which will remain functional from version to version (occasional API deprecation or function renaming withstanding -- but that's no different than Early Access), and I won't have to deal with synching code or making pull requests, especially the perhaps-small possibility of my changes being rejected from the trunk and therefore having to rewrite to use this "solution" instead in the first place.

Most of my wishlist which I haven't bothered anyone with would require engine support at one point or another, but since it overlaps rather substantively with the planned "vehicle overhaul" that everyone's muttering about a little on Github, I've been holding off on worrying over it...

I've been debating trying MSYS2 instead, but need to muster up another half-hour of attention span. ;-)