Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 21 22 [23] 24

Author Topic: Roses' Script, System, and Utilities Collection (07/06/2021)  (Read 87442 times)

Evans

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #330 on: November 23, 2020, 06:23:44 pm »

Just for clarification, what exactly happens? The cage gets thrown correctly, and the target gets put in the cage correctly, but the unit keeps attacking the caged target? More than one attack, or just a single extra attack?
There was once this bug where squads ordered to kill target followed target after it was caught by cage trap.

It's the same - hunter wants to hunt/return kill, squads ordered to kill stay at that order and follow caged target.

Here is the script, I will refactor it a bit later, if I deal with this follow issue :S
Spoiler (click to show/hide)
Logged
getlost.lua # How to get rid of tavern guests
function getlost ()
   local unit = dfhack.gui.getSelectedUnit (true)
   unit.flags1.forest = true
end
getlost ()

Roses

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #331 on: November 24, 2020, 01:01:55 pm »

Figured out was the problem. You didn't have a plural name for the example items. It should've been
power digger:power diggers.

But that's honestly a minor thing.
I got a question are the skills and attributes changes attached to the item invisible? Or are they suppose to show up in you the player's stats?

It looks like several of the hooks for the attribute and skill changes are not working correctly. I was testing using the {SCRIPT} command, so that is my fault. I'll get the hooks correct and upload a new version. Sorry for the inconvenience.

Just for clarification, what exactly happens? The cage gets thrown correctly, and the target gets put in the cage correctly, but the unit keeps attacking the caged target? More than one attack, or just a single extra attack?
There was once this bug where squads ordered to kill target followed target after it was caught by cage trap.

It's the same - hunter wants to hunt/return kill, squads ordered to kill stay at that order and follow caged target.

Here is the script, I will refactor it a bit later, if I deal with this follow issue :S

Looking at the code briefly I see this part, which looks like it's trying to do what you want, but the if statement will never read true because it is comparing an id to a unit struct
Code: [Select]
local allUnits = nil
allUnits = df.global.world.units.all
--make other units stop following it
for i=#allUnits-1,0,-1 do -- search list in reverse
newu = allUnits[i]
if newu.opponent.unit_id == unit then
newu.following = nil
newu.enemy = nil
newu.opponent.unit_id = nil
newu.job.hunt_target = nil
end
end

Try changing if newu.opponent.unit_id == unit then to if newu.opponent.unit_id == unit.id then and see if that works.
Logged

Evans

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #332 on: November 24, 2020, 03:32:31 pm »

Looking at the code briefly I see this part, which looks like it's trying to do what you want, but the if statement will never read true because it is comparing an id to a unit struct

Try changing if newu.opponent.unit_id == unit then to if newu.opponent.unit_id == unit.id then and see if that works.

Script now looks like that:
Spoiler (click to show/hide)
Log shows no bugs, but nothing really changed. Seems like 'following' is no longer used (I've monitored the engangement with gui/gm-editor) as it is always nil and opponent is only used during the actual attack.

Targeting for hunt/kill job seems to be kept elsewhere :/

I can't seem to find a field tho...

Hmm... Is there maybe a way to peak into job data somewhere?
« Last Edit: November 24, 2020, 03:36:48 pm by Evans »
Logged
getlost.lua # How to get rid of tavern guests
function getlost ()
   local unit = dfhack.gui.getSelectedUnit (true)
   unit.flags1.forest = true
end
getlost ()

Roses

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #333 on: November 24, 2020, 06:11:40 pm »

Darn, was hoping it would be a simple fix. One other simple thing you could try would be to change the units path goal newu.path.goal = -1, that might reset them. You can also try to remove any jobs they might currently have with
Code: [Select]
newu.job.current_job = nil although I would be a little concerned that that might leave a hanging job on the list and cause issues if it happens to much. But if that does fix it, then it would be simple enough to properly remove the job instead of just unassigning it.
Logged

Evans

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #334 on: November 25, 2020, 01:42:57 pm »

Darn, was hoping it would be a simple fix. One other simple thing you could try would be to change the units path goal newu.path.goal = -1, that might reset them. You can also try to remove any jobs they might currently have with
Code: [Select]
newu.job.current_job = nil although I would be a little concerned that that might leave a hanging job on the list and cause issues if it happens to much. But if that does fix it, then it would be simple enough to properly remove the job instead of just unassigning it.

There is something odd about all this.
The code:
Spoiler (click to show/hide)
I've added some logging to see what happens, and IF is executed properly. But here is the thing.
The unit seems to be loosing current job, as expected, but only for a split second and then it gets that job back... still following the target :)

I'm actually wondering about stealing some of your code for action cancelling and seeing what happens. You think that maybe '_action.type = -1' could help? :/
Logged
getlost.lua # How to get rid of tavern guests
function getlost ()
   local unit = dfhack.gui.getSelectedUnit (true)
   unit.flags1.forest = true
end
getlost ()

Evans

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #335 on: November 25, 2020, 02:02:35 pm »

edit:

I think I'm getting somewhere.
The script now looks like this:
Spoiler (click to show/hide)
...aaaand it seems it works. I don't know what happens in the loop we were discussing earlier, but it works.
Nothing can be done about soldiers, it seems, as it is possible to issue kill order for caged animal to a squad.

But now there remains one last thing :(
A lingering hint under the cursor about the creature that persists between save and reload.
« Last Edit: November 25, 2020, 03:47:56 pm by Evans »
Logged
getlost.lua # How to get rid of tavern guests
function getlost ()
   local unit = dfhack.gui.getSelectedUnit (true)
   unit.flags1.forest = true
end
getlost ()

Warmist

  • Bay Watcher
  • Master of unfinished jobs
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #336 on: November 26, 2020, 05:41:27 am »

Evans

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #337 on: November 26, 2020, 03:22:10 pm »

<...>

You need to mark that map tile as empty of creatures- see here: https://github.com/DFHack/scripts/blob/master/teleport.lua#L32
Wow. Thanks.

Edit:
Ok, here I'm trying this:
Spoiler (click to show/hide)
Both first things do not solve the problem, hint persists.
Last line with either nil or false returns an error.

What should I set in here? What am I missing? :S
Logged
getlost.lua # How to get rid of tavern guests
function getlost ()
   local unit = dfhack.gui.getSelectedUnit (true)
   unit.flags1.forest = true
end
getlost ()

Atomic Chicken

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #338 on: November 27, 2020, 01:35:43 pm »

...

Code: [Select]
local eventful = require 'plugins.eventful'

function getItemType(item)
  if item:getSubtype() ~= -1 and dfhack.items.getSubtypeDef(item:getType(), item:getSubtype()) then
    return dfhack.items.getSubtypeDef(item:getType(),item:getSubtype()).id
  else
    return df.item_type[item:getType()]
  end
end

function createCage(material, quality)
  local item = df.item_cagest:new()
  item.id = df.global.item_next_id
  df.global.world.items.all:insert('#',item)
  df.global.item_next_id = df.global.item_next_id+1
  item:setMaterial(material.type)
  item:setMaterialIndex(material.index)
  item:setQuality(quality)
  item:categorize(true)
  item.flags.removed = true
  return item
end

function getCaptureProbability(unit)
  local damageFactor = 1
  if unit.counters.winded > 0 then
    damageFactor = damageFactor/1.5
  end
  if unit.counters.stunned > 0 then
    damageFactor = damageFactor/1.5
  end
  if unit.counters.unconscious > 0 then
    damageFactor = damageFactor/2
  end
  if unit.counters.webbed > 0 then
    damageFactor = damageFactor/1.5
  end
  if unit.counters.nausea > 0 then
    damageFactor = damageFactor/1.5
  end

  local bloodFrac = 1
  local bloodMax = unit.body.blood_max
  if bloodMax ~= 0 then
    bloodFrac = unit.body.blood_count/bloodMax
  end

  return 100 - ((unit.body.size_info.size_cur*10 ^ 1/3)*bloodFrac*damageFactor)
end

function cageUnit(cage, unit)
  local containedIn = df.general_ref_contained_in_itemst:new()
  containedIn.item_id = cage.id
  unit.general_refs:insert('#', containedIn)
  unit.flags1.caged = true
  unit.flags1.on_ground = false
  local tileOccupancy = dfhack.maps.getTileBlock(unit.pos).occupancy[unit.pos.x%16][unit.pos.y%16]
  tileOccupancy.unit = false -- would probably be better to check whether there are other units on the same tile before disabling these
  tileOccupancy.unit_grounded = false

  local containsUnit = df.general_ref_contains_unitst:new()
  containsUnit.unit_id = unit.id
  cage.general_refs:insert('#', containsUnit)
  cage.flags.container = true
end

eventful.onProjItemCheckImpact.capture = function(projectile)
  local firedItem = projectile.item
  if not firedItem then
    return
  end

  if string.find(getItemType(firedItem), "_PROJCAGE", 9) then -- replace as necessary
    local material = dfhack.matinfo.decode(firedItem)
    if not material then -- shouldn't happen
      return
    end

    local targetUnit
    for _, u in ipairs(df.global.world.units.active) do
      if u ~= projectile.firer then -- prevent firer from capturing themself
        if same_xyz(u.pos, projectile.cur_pos) then -- find a unit at the same location as the projectile
          targetUnit = u
          break -- only a single unit will be captured
        end
      end
    end
    if not targetUnit then -- nothing to capture at the impact location
      return
    end

    local cage = createCage(material, firedItem.quality)
    dfhack.items.moveToGround(cage, targetUnit.pos)

    if math.random(100) > getCaptureProbability(targetUnit) then -- removing this will guarantee capture
      cageUnit(cage, targetUnit)
    end

    projectile.flags.to_be_deleted = true -- ensures that the fired item doesn't persist

--  make other units stop following the captured unit:
    local allUnits = df.global.world.units.all
    for i = #allUnits-1, 0, -1 do
      local unit = allUnits[i]
      if unit.following == targetUnit then
        unit.following = nil
      end
      if unit.opponent.unit_id == targetUnit.id then
        unit.opponent.unit_id = -1
        unit.path.goal = -1
        unit.job.current_job = nil
        unit.job.hunt_target = nil
      end
    end
  end
end

Tidied up your script whilst looking into the "phantom unit" issue. It also appears to occur with creatures that are captured via regular cage traps, so I'd say that this is a more of a problem with the way DFHack generates the "units under the cursor" display (cursor support isn't a vanilla feature), as opposed to anything specifically wrong with this script.

Looks like the script incorporates a Pokemon-esque mechanic which makes capturing easier the more damaged the target is. I didn't examine it closely, but it might need some fine-tuning as the bulk of my test units were caught on first attempt.

For future reference, enclosing code in a "code" block as opposed to a "spoiler" makes it easier for others to read and copy. Also, this particular thread might not be the most appropriate place to ask for scripting advice; opening a new one or continuing the discussion in the general DFHack thread would make it easier for others to notice your queries whilst preventing accidental derailing.
« Last Edit: November 27, 2020, 02:14:08 pm by Atomic Chicken »
Logged
As mentioned in the previous turn, the most exciting field of battle this year will be in the Arstotzkan capitol, with plenty of close-quarter fighting and siege warfare.  Arstotzka, accordingly, spent their design phase developing a high-altitude tactical bomber. 

Evans

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #339 on: November 27, 2020, 04:09:58 pm »

Tidied up your script whilst looking into the "phantom unit" issue. It also appears to occur with creatures that are captured via regular cage traps, so I'd say that this is a more of a problem with the way DFHack generates the "units under the cursor" display (cursor support isn't a vanilla feature), as opposed to anything specifically wrong with this script.
Whoah. Thanks.
Compared to yours, it's a miracle mine was even working.

Anyway,
Quote
Looks like the script incorporates a Pokemon-esque mechanic which makes capturing easier the more damaged the target is. I didn't examine it closely, but it might need some fine-tuning as the bulk of my test units were caught on first attempt.
True, I think original author (was it IndigoPhoenix) had something like that in mind. I've actually seen capture failed few times, but on bigger animals, so it might just work, somewhat :)

Quote
For future reference, enclosing code in a "code" block as opposed to a "spoiler" makes it easier for others to read and copy. Also, this particular thread might not be the most appropriate place to ask for scripting advice; opening a new one or continuing the discussion in the general DFHack thread would make it easier for others to notice your queries whilst preventing accidental derailing.
I'll keep that in mind. I thought maybe posting large blocks of unclean code wasn't such a smart idea ;)
And my apologies to Roses for hi-jacking this thread. I made a search through available lua scripts and Roses scripts were the only I've found where an action was cancelled.

Seems like this Phantom Menace won't go away any time soon, so cage guns will remain of limited use. But so far it is working, at least to some extend.

Thank you guys for help.
Logged
getlost.lua # How to get rid of tavern guests
function getlost ()
   local unit = dfhack.gui.getSelectedUnit (true)
   unit.flags1.forest = true
end
getlost ()

Roses

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #340 on: May 21, 2021, 01:09:20 pm »

You know its been a long time when you are getting an old topic warning when posting in your own thread...

So after a very hectic year, I am finally getting back into a point where I can do some DF stuff. It looks like a left off with a few fixes needed for for the EnhancedItems and testing needed for Adventure mode. I also need to investigate if there have been any major changes to DFHack that I should be including. I will probably need some testers in the near future for some other stuff I am planning on implementing, but for now I just need to get back into the feel of DF.
Logged

myk

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #341 on: May 25, 2021, 02:12:28 pm »

Hi Roses! Welcome back! I've been seeing your name in the code a lot, but we've never met. I've been making a lot of changes recently to quickfort (there's one in DFHack now, not the external Python one), buildingplan, and blueprint.

I'm also working on a few utility plugins that might be useful for you -- dig-dug to dig out sections of rock according to dig designations and build-now (or something.. I haven't really thought of a name yet) for instantly completing construction jobs. My use case is automated regression testing -- apply a blueprint file with quickfort, use dig-dug and build-now to make things happen without dwarven intervention, create blueprint files from the resulting game map with blueprint, and compare the input and output files -- but you might be able to use them for making general changes to the game map.

There's also a database of building metadata in quickfort that we might be able to factor out and share.
Logged

Roses

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #342 on: May 27, 2021, 11:44:30 am »

Hi Roses! Welcome back! I've been seeing your name in the code a lot, but we've never met. I've been making a lot of changes recently to quickfort (there's one in DFHack now, not the external Python one), buildingplan, and blueprint.

I'm also working on a few utility plugins that might be useful for you -- dig-dug to dig out sections of rock according to dig designations and build-now (or something.. I haven't really thought of a name yet) for instantly completing construction jobs. My use case is automated regression testing -- apply a blueprint file with quickfort, use dig-dug and build-now to make things happen without dwarven intervention, create blueprint files from the resulting game map with blueprint, and compare the input and output files -- but you might be able to use them for making general changes to the game map.

There's also a database of building metadata in quickfort that we might be able to factor out and share.

Those do sound like useful utilities, I have something similar in a script that takes a building name and position and constructs a fully operational building (building/create.lua), but it isn't as advanced as what I am seeing in your script (I also have a small database of hardcoded buildings (functions/building.lua), but again, not as advanced as yours). I will definitely look into your stuff, I am particularly interested in dig-dug since I think it would be really cool to make "geomancy" type magic that manipulates the map and such. I've only played around with very basic map manipulation, mostly just removing trees/bushes (functions/plant.lua), and checking tiletypes and such (functions/map.lua), not much actually changing things.
Logged

myk

  • Bay Watcher
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #343 on: May 29, 2021, 12:27:54 pm »

plant.lua looks like exactly what I need to simulate tree chopping. I was worried that I'd just have to ignore trees entirely if I couldn't figure it out! Do you mind if I add that to either dig-dug itself or the dfhack core library?

tiletypes might also be useful to force a tile into a particular shape/configuration. I'm writing dig-dug because I specifically want the tile tile transformations to follow the rules of "organic" digging.

If you think you could use the quickfort buildings db, I can work on putting it behind an API so it's queryable by multiple indices (e.g. by type,subtype,custom instead of its current "ui keystroke sequence" map key
Logged

Bumber

  • Bay Watcher
  • REMOVE KOBOLD
    • View Profile
Re: Roses' Script, System, and Utilities Collection (10/13/2020)
« Reply #344 on: May 29, 2021, 04:05:28 pm »

plant.lua looks like exactly what I need to simulate tree chopping. I was worried that I'd just have to ignore trees entirely if I couldn't figure it out!

I don't understand everything that's going on in the script, but it doesn't look like it will cause items to fall out of the removed tree, or water to recalculate. In other words, it's equivalent to using a ballista bolt.

dfhack.items.makeProjectile can be used to cause an item to fall, and liquids plugin probably has the proper way to update fluids. Should be simple enough to implement.



I've been preparing to disassemble the exact code for tree chopping by starting with understanding the less complex function for finding a plant at a tile (that the tree chopping function calls.) Knowing I'm probably seeing:
Code: [Select]
y_column = math.floor(base.y/16)
y_column-y_column%3
when I'm looking at
Code: [Select]
movsx   r12d, r8w ; y coord into r12
mov     eax, 2AAAAAABh
imul    r12d
mov     edi, r12d
movzx   ecx, r12w
sar     edx, 3
mov     eax, edx
shr     eax, 1Fh
add     edx, eax
lea     eax, [rdx+rdx*2]
shl     eax, 4
sub     edi, eax
sub cx, di
mov     [rsp+30h+arg_8], edi
is very helpful!

Edit: Actually, looks like the above assembly calculates math.floor(base.x / 48) * 48 and base.y%48 (which it later uses with dim_y to completely avoid using extent_north, etc.)

The optimized code used by DF is:
Code: [Select]
map_block_column = df.global.world.map.column_index[(math.floor(base.x / 48) * 48) / 16][(math.floor(base.y / 48) * 48) / 16]which avoids %3.
« Last Edit: June 01, 2021, 03:14:54 am by Bumber »
Logged
Reading his name would trigger it. Thinking of him would trigger it. No other circumstances would trigger it- it was strictly related to the concept of Bill Clinton entering the conscious mind.

THE xTROLL FUR SOCKx RUSE WAS A........... DISTACTION        the carp HAVE the wagon

A wizard has turned you into a wagon. This was inevitable (Y/y)?
Pages: 1 ... 21 22 [23] 24