Changelog:
0.5c fixed blunderbuss errors and added WIP rocket launcher wall breaching
0.5b fixed some raw errors (thanks to DWARFFRAWD and Sver)
0.5 updated for Meph tileset V4.2
added Alchemist's Laboratory and reimplemented chemical weapons
added lightning gun
added new ammo sprites and retouched weapon sprites
improved cannon reactions (firer will now wait for target and fire at will), fixed targetting distance error and made rotation compatible with other mods with much assistance from Grimlocke
merged weapon scripts preventing them tripping up over each other
tweaked automusket to use regular bullets, lowered smoke amount and slightly increased accuracy
increased number of blunderbuss pellets from 4 to 6
slightly increased rocket explosion size and made flight path become unpredictable after 30 tiles of flight
0.4i updated for Meph tileset V.4
0.4h made cannonball more effective (thanks to Grimlocke)
fixed automusket listener name error
0.4g tweaked cannon pathing algorithm to be more accurate
rolled back settings manager changes due to arena mode scripts not firing
0.4f added automusket
tweaked settings manager to try and lower overhead whilst retaining arena mode functionality
0.4d added cannon rotation, separate fire and load reactions at Grimlocke's suggestion, also native-like announcements
added Vordak's cannon sprites
added cave-in dust concussion effect to hand mortar grenades
fixed blunderbuss ammo name error
attempted to make normal cannonballs more deadly by increasing velocity & velocity multiplier
0.4c added blunderbuss and dragon pistol
0.4b moved reactions into appropriate workshop categories
0.4 added ingame customization menu letting users select which weapons appear in fortress mode
added Vordak's weapon sprites
added Gunsmith's workshop (sprite by Meph) so as to not gum up the metalsmith's menu with reactions.
added flintlock pistols and bayonets
added notification when cannon user cannot find valid target
added new reaction to cannon to allow targetting of helpless domestic animals for test-firing
0.3c added gun carriage to cannon sprites and changed skill used by firearms to blowgun, as per Vordak's advice
0.3b added hand mortars at the request of MottledPetrel
0.3 initial release
Please, make a hand mortar, it's my favorite black powder fire arm.
I think that for gunpowder and any new ranged weapons need to use the skill BLOWGUN - this will allow to draw graphics for rifledwarves, it will allow a clear distinction between different types of ranged military. Besides, dwarves (players) do not use blowguns.
Upd.
This is ridiculously cool. I am especially impressed by the rocket launcher and the smoke effects.
I'm glad you like it! The handheld weapons use very simple scripts, I was surprised I hadn't seen anyone do it before.
The cannon was much more difficult for me to make, but everyone seems to like the rocket launcher the most. Oh well. ¯\_(ツ)_/¯
Your rifledwarf sprite is impressive, I don't suppose you have any musket item sprites you don't mind me using?(https://i.imgur.com/FJ2u2iY.png)
I'd be sure to credit you. Would be much better looking than me just mashing together stuff from metal slug.
Why not a flamethrower? Adding firebreath to the wielder shouldn't be too hard.
It's just the sprite of your gun rotated by 45 degrees. Use if necessary, credit do not need.
I think portable rocket launchers are too much - in my opinion it is better to make it as a siege weapon - it's just a wish. Better it would be something like mortars.
Why not a flamethrower? Adding firebreath to the wielder shouldn't be too hard.
Oooh, interesting. Especially like how you added smoke. I might try and adapt these scripts to my own mod in the future.
You could make the distinctions i made in MasterworkDF: pistol, one handed, musket, two handed. Both in normal and in a bayonetted version.
Well, well, a custom gunsmith you say? 8)
Will you ever do grenades or landmines?
What are some of those sprites on the original post that aren't yet in the mod? That harpoon with an (what I assume to be) explosive charge looks interesting.
And for more suggestions, how about a nock gun? I have no idea if you can script a gun that fires seven shots at once, but it would be pretty cool. And if you manage to figure that out, making a duck's foot pistol wouldn't be that different. A blunderbuss could be made in similar effect, albeit much more inaccurate, short ranged, and devastating.
To a similar effect, a grapeshot charge would be good for cannons when your target isn't an elephant. For the elephants an elephant gun for excessive caliber needs. A double barrelled turn over pistol could be used for two quick shots followed by an extended reload time. A french knife pistol could be exactly what it says on the tin, a well crafted knife with a usable pistol built into it. But at the very least, I would STRONGLY recommend the German axe pistol.
Having little prior knowledge of scripting, I don't know how many of these can actually be done or are practical to do, but I just thought I'd give some ideas. All suggestions are based off of real fire arms from the 1800's or prior.
Maybe make the flamethrower like the cannon? Triggers dragonfirebreath in a cardinal direction when used?
Your understanding of traps is correct. I did bombs in masterwork like that using the projectile-trigger script. The other Form of landmine was a creature using a short range interaction. That gave invaders the Chance to disable them with ranged weapons, but also enabled wonderful murder holes just like in RL.
Make gate, inner gate, trap invaders in between. One zlvl above, pit/pasture the landmine down a hatch into the room below. :-)
The problems with using dfhack.maps.spawnFlow are: I don't know how to make directed jets (like firebreath or webs) or trailing flows (might be useful for gas cannisters).
you could change reload time and shot frequency with dfhackI would be interested in knowing how. I've spent more hours than I'd like to admit going through the data structures, trying to find some cooldown variable.
I have spent the last several days messing around with flows, first in an attempt to spawn webs for barbed wire (a partial success, but only with the help of 2 different scripts and it isn't effective enough to matter) and then in an attempt to make a 1-tile creature look like a sandworm (works really well, but since it fires every 5 ticks regardless of whether there's a worm or not it adds too much overhead to be practical).I'd be interested to see the sandworm script, I was messing about with multi-tile giant snakes by chaining the positions of multiple creatures which worked well but fired every tick and would need seperate raw definitions for the different bits so the snake didn't have multiples of every organ. Your method sounds much better! Are you working on a Dune mod?
Anyways, I have had the displeasure of getting to know the internal workings of flows better than I would like to. You can create aimed flows by spawning the flow, and then setting the destination of that flow to whatever you want while it's still only 1 tile big. This doesn't work with everything- I know that it works with dragonfire and webs, but not with MaterialGas. I don't know about the other flows, but I suspect you can find out what how to do trailing flows by examining the flows that come out of creatures that have that interaction
I would be interested in knowing how. I've spent more hours than I'd like to admit going through the data structures, trying to find some cooldown variable.
I'm not working on a full-blown dune mod, mostly just the sandworms. Because sandworms are cool.
Range of flows: I don't actually know that much about how the spawnflow function works so idk exactly what size does. I know density of the flow controls range, but returns very much diminish. I suggest constantly multiplying the density to make it go down slower since it doesn't decrease linearly.
As for the mechs, I'm not that well versed in raws but I'm pretty sure that's an interaction token, so it isn't actually relevant for bow/gun firing rate (though you can simulate a machinegun or whatever by just giving the creature an interaction)
I take it this works with Meph's launcher thingy?
Oh god.
DF. Dune Fortress.
Dont give me ideas.
(yes, i meant like a siege engine flamethrower, maybe triggered by a lever or pressure plate)
...
also, if MottledPetrel is correct when he says thatyou could change reload time and shot frequency with dfhackI would be interested in knowing how. I've spent more hours than I'd like to admit going through the data structures, trying to find some cooldown variable.
...Ooh, ooh, ask me, ask me, I know things!As for the mechs, I'm not that well versed in raws but I'm pretty sure that's an interaction token, so it isn't actually relevant for bow/gun firing rate (though you can simulate a machinegun or whatever by just giving the creature an interaction)I see. I vaguely remember reading a certain skill might have a bearing on fire rate, whatever it was could be temporarily manipulated to modulate the rate to the desired amount.
...
Sorry I couldn't be more helpful to return the favour.
Ooh, ooh, ask me, ask me, I know things!
The variable (Firing Unit).counters.think_counter is set whenever a ranged weapon is fired. The variable is set to a number that is related to a creature's weapon skill (agility and ranged combat don't appear to do anything, haven't checked any other attributes), and will lie somewhere between 80 (dabbling) and 40 (an obscenely high legendary rating), with 48 being the practical limit for legendary weapon users. Once set, the variable ticks down until it reaches 0, at which point the creature can fire again that tick. Adjusting the think_counter variable of a creature with dfhack will directly adjust the time until the creature fires again.
...I was planning on writing a rate of fire script myself at some stage, when I wasn't busy with other stuff. But if you want to beat me to it (and let me "borrow" it), I will not be complaining.
Thanks for the info about Unit.counters.think_counter, thefriendlyhacker. So much potential for new weapons!
...Not only that, but if the script kept track of when/how many times a creature fired recently, it would be possible to have burst weapons. You could also combine it with the multi-projectile shot script zaporozhets has for fun things like quad barrel or mag fed automatic shotguns with appropriate reload delays.
Miniguns.
Quick-fire crossbows.
Differences between bow types.
Awesome!
I was planning on writing a rate of fire script myself at some stage, when I wasn't busy with other stuff. But if you want to beat me to it (and let me "borrow" it), I will not be complaining.
While I am posting, here is a question. Would it work if you created more projectiles on a projectile weapon's impact to simulate a fragmentation explosive? That was an idea I came up with a while back, but I never got around to looking into the implementation details seriously.
thefriendlyhacker's info should also let me reduce firing rate of the handcannons and arquebusses I have laying around from way back which is arguably less exciting than making machine guns but will actually let me fit them in with armor and crossbows balance-wise. Soooo, cool!
I've been tinkering with the cannon, and I think it should be feasible to make a gun that just shoots solid cannonballs and grapeshot as well as an (also stationary) organ gun. (something something check the input item type and loop the projectile function a bunch of times)
Have you thought about less RL weapons and more in the line of magic weapons?
Staff of fireball = rocket launcher alternative that fits df.
Or spelltome of rock barrage = shotgun-like effect.
Have you had any problems with it? I've not had anyone report bugs which is quite strange.
I know they sometimes try and fire through closed doors if the nearest enemy is behind (they don't yet check for buildings on a tile) but I want to know if I should make the make the pathing function parameter dynamic, so as to be more reliable in choosing a clear path (at the expense of more overhead).
Has it worked well enough for you?
I agree with your thoughts, seems very feasible! Were you thinking of making it fire item_ammo (item_ammos?), or use a different method of stopping trapcomp fire altogether?
A static organ gun is a rad idea, much better than the affront to native balance I posted above.
I'd like to do something similar but with a lower fire rate than an organ gun firing weak rockets that veer away and oscillate at random to make a katyusha/nebelwerfer/hwacha thingy as a more sane version of the rocket launcher.
I said it before, but I look forward to seeing the fruits of your tinkering.
The cannon so far worked without outright bugs (I hadn't come across any situation where buildings were in the way yet). The only oddity I had was my gunner persistently shooting to the bottom right with nothing there for some time but I suspect that was due to me sabotaging the hostility check (I didn't feel like waiting for a nicely grouped bunch of goblins to show up, so my own dwarves and some bards volunteered for projectile testing) perhaps causing it to target something it shouldn't be.
Some features I do miss is targeting being restricted to cannon orientation. My planning was to make a heavier, fixed bombard on a 3x3 building plot that would only rotate on manual command (using a building transform script), and a light 1x1 swivel-mounted gun that could fire in any direction. Having large guns be mostly fixed, defensive things you would generally place along ashooting gallerywelcoming entrance, the building collision issue might only be problematic with raised bridges.
I'd say that if targeting being blocked by buildings and orientation-restriction are both impossible with the current targeting implementation, it might be worth going with something with more overhead. Its not like the targeting script it run that frequently.
One other feature I would appreciate is a separate load and fire command, which I could probably implement myself once I figure out how to make very short-duration reactions. Being able to have accurate commands at when and where guns fire would help a lot in keeping down the number of hilarious friendly fire incidents.
Edit: I'm not sure what to make of these two lines in the cannon script:
output_items[0].skill_used = input_items[0].mat_type
output_items[0].sharpness = input_items[0].mat_index
Roses building-subtype-change script enables rotating your workshop. Its a bit complicated, because you'd need to make 4 separate workshops, but it works well.
Yeah, if you rotate, use square designs. Sneaking of which, any sprites needed for those?
Roses building-subtype-change script enables rotating your workshop. Its a bit complicated, because you'd need to make 4 separate workshops, but it works well.
Cannon tubes.
(https://i.imgur.com/NuLiZod.png)
I just read grimlocks Post about swivel guns, etc and thought you had more workshops / fake siege engines coming up.
So... You just need the cannon, right?
I actually did not plan drawing anything except tubes, but ok, I do it. It is planned to leave cannons in size 1x2 tiles?
Yeah, but the workshop sprites can be transparent, doesnt have to look like a square.
I would have made a circle, with tracks on it, and a cannon positioned on them. I think it would look quite striking in comparison to otherwise rectangular workshops.
Perfect. :-)No problem.
Mind if I do the rest?
(https://i.imgur.com/f8vNVDE.png)
I present: The VoMeZa-Cannon!When you said a circle with tracks on it, I thought you were going to do a little railway loop with the gun facing outwards and perpendicular to the tracks, so rotating the gun would just be a matter of pushing the rail cart through 90 deg of track, and the firer would stand in the center of the rail loop while firing the gun. I just figured I would bring it up as an alternative design you could try if you wanted.
(https://i.imgur.com/YMFeFky.png)
What do you think? It's mostly Vordaks sprites, even the tracks are his. ^^ He improved the ones I had in my tileset once.
With TWBTnext you have transparency, so the workshop appears round, the corners will look like the floor below it.
(https://i.imgur.com/fR6uElt.png)(https://i.imgur.com/sg5lLvs.png)
I could just be suffering from sleep deprivation but the 'swivel' one doesn't appear to be centered. Is it a problem with creating a circle with so few pixels or a mishap?I corrected the offset.
That was impressive to watch, like a collaborative argument between artists.Do not be so tense - choose one at your discretion.
I probably won't add both types in at once as separate cannons to make the scripting easier on myself, but to respect Vordak's wish and to give players a choice of which they prefer, I'll include both in separate install folders.
I corrected the offset.
Do not be so tense - choose one at your discretion.
Here's where I'm at with my own efforts with the handheld firearms, which kind of sprawled into a script to modify any projectile: https://pastebin.com/j07S30Nb
Right now it modifies accuracy, velocity, firing rate, hit rate (to account for shot weapons that should be harder to dodge), chance of breaking on impact (needed that for a thrown weapon), whether it pierces through stuff or not and how many extra projectiles it spawns of which item subtype.
A few lingering issues I'm still having and could use some advice on are that I can't quite think of a way around: I'm trying to have it do stuff based on the weapon used, so that I can slow down firing rate for heavier crossbow (using the same ammunition). The projectile data structure has a 'bow_id' value, which is a number starting at 0 and increasing as more items are spawned in the map. It clearly corresponds to the specific ranged weapon used, but its not an item ID and I can't get any of the item functions to do anything useful with it. I suspect there's some obvious way of using that that I'm missing.
Also I've been trying to change the item type of projectiles, which is easy enough for the subtype (using item.setSubtype), but setType doesn't exist. Is there some other way of doing this or do I just have to delete the original and spawn a new projectile?
And as an aside, I've noticed that the 'piercing' flag behaves weirdly and causes a single projectile to hit the same target numerous times, sometimes killing them dead instantly, before passing through. Might be useful to simulate explosives? Change the material to something with huge shear value and give the projectile plenty of contact area/surface and it should make giblets easily enough.
Edit: Just found that the shot projectiles can only hit one target one time, even though a single shot can hit multiple enemies at once. Even at close range the a single enemy only gets hit by one projectile while the rest merrily goes on its way.
Could I include the rocket launchers in the dune mod I'm creating? They really are amazing, and proper credit would obviously be given.
...I wouldn't be so concerned with overhead if I was you. If you are doing checks that only happen during combat, then any overhead caused by those checks will be hidden by the massive slowdown caused by combat. No sane amount of searching through memory is going to compare to the herculean task of writing "The goblin lasher dodges the steel bolt" to hard drive. Unless you are doing something that iterates through lists multiple times on a constant near tick by tick basis, don't even bother worrying about performance, because your dinky little script's overhead will be lost in the sea of RAM sundering computation cycles that is Dwarf Fortress.
I've had this issue too and just sidestepped it by giving the weapon a new ammo, the only way I could think of using the same ammo was iterating through the firers inventory on distance_flown == 0, getting projectile.firer.inventory[indx].item.subtype.id and checking against the weapon name (or checking subtype.subtype, but I like strings for readability), but it was for the automusket and I was worried about the overhead and so didn't go any further with it. Hope that works for you.
...
I wouldn't be so concerned with overhead if I was you. If you are doing checks that only happen during combat, then any overhead caused by those checks will be hidden by the massive slowdown caused by combat. No sane amount of searching through memory is going to compare to the herculean task of writing "The goblin lasher dodges the steel bolt" to hard drive. Unless you are doing something that iterates through lists multiple times on a constant near tick by tick basis, don't even bother worrying about performance, because your dinky little script's overhead will be lost in the sea of RAM sundering computation cycles that is Dwarf Fortress.
It's lovely of you to ask, of course you can! I've been messing about with a lasgun that makes an instant beam of 'laser' and one that has a more simple 'blaster' trail as well, but I'm not happy with the results are so far (fire rate is just to make testing easier):
(https://i.imgur.com/ESrlavR.gif) (https://i.imgur.com/HX1DHJz.gif)
Your thread seems to indicate you also have a preliminary version of it as well, I'd love to see it. I want to try my hand at the beam-shield interaction.
onProjectileHit:
if projectile.type == beam and projectile.target.isShielded() then
spawnflow(a fuckton of dragonfire, maybe some smoke, cave in dust, at target.pos and shooter.pos)
end
end
Very impressed after a cursory reading. As a fellow noob to lua, I did not know you could set table keys like that.
I did notice you set multiProjectile.distance_flown to 6 to avoid smoke, I initially did something similar on the blunderbuss before I noticed it seemed to be teleporting the projectiles forward. It's not a problem really unless the target is nearly adjacent.
Making a general purpose projectile script is a brilliant idea.
I've had this issue too and just sidestepped it by giving the weapon a new ammo, the only way I could think of using the same ammo was iterating through the firers inventory on distance_flown == 0, getting projectile.firer.inventory[indx].item.subtype.id and checking against the weapon name (or checking subtype.subtype, but I like strings for readability), but it was for the automusket and I was worried about the overhead and so didn't go any further with it. Hope that works for you.
Interesting stuff. I'll need have to have more of a mess around with the projectile flags, I have no idea what I'm doing with them. I just copied them in from Roses projectile script and I keep getting a weird bug on the cannon where it only causes light bruising, setting the piercing flag seemed to fix it but now I'm not so sure it did what I thought given what you've said. Maybe I should just make the cannonball use an edge attack. Has anything like that happened to you?
Wow, I don't know what you are unhappy with. That's impressive, especially the first one. How did you get the beam to work? It can't just be flows spawned on the bullet because it's moving faster than a tile a tick.
To clarify, I don't actually have any real code written (aside from the samdworm prototype), just a bit of pseudocode. I've been forcing myself to do the raws first, because that's the harder part for me and also the more important one for the mod. A beam-shield interaction should be pretty simple, something along the lines ofCode: [Select]onProjectileHit:
if projectile.type == beam and projectile.target.isShielded() then
spawnflow(a fuckton of dragonfire, maybe some smoke, cave in dust, at target.pos and shooter.pos)
end
end
Ah... I hadn't noticed, but this sure explains the issue of shot projectiles not hitting stuff. Thanks, I'll have to come up with something else for that. I've also manually carried over the firer ID to the multiProjectile since the one in makeProjectile didn't seem to work; shot projectile hit combat reports weren't showing as coming from the player character in adventurer mods.
Hmm yeah, I considered something like that but I had hoped I could circumvent it by using the bow_id. It does seem to correspond to whatever ranged weapon is being used, but I can't figure how to use it. Anyhow, thefriendlyhacker probably had a point, I'll give your idea a try.
Some blunt objects seem to have that effect, I've set cannonballs to be edged since they pretty much behave that way judging by historic records. Piercing is appropriate for cannonballs too, since they tended to tear through lines with fairly little regard for how many soldiers were in the way.
Oh my god.It is all pretty cool, isn't it?
May I also have access to the laser lua stuff, for an animorphs mod I'm working on?
Here's what I have for raws right now: https://pastebin.com/NcNidFzE of course, use whatever you like; I don't think anyone here is particularly possessive of their work and would much rather it see use in whatever way. Its really a very pleasant community we've got here.
On that note I hope everyone here who wants it grabs all this stuff before I get into a really bad mood.zaporozhets looses a roaring laughter, fell and terrible!
Thanks for the consideration about the toes, but honestly don't worry about it. I looked over the laser code, it looks good. The functions flow pretty well, the implementation is elegant, and the only part that really bothers me about it is when you copy the entire projectile variable by variable- It seems easier to just change the existing cartridge projectile's type into a laser beam.
idk if I'll actually use your laser, I'm not at that point yet and I'm planning for some complex artificial AI to be involved (the whole mindgame of "do I risk firing in case he has a shield?" and "should I use a shield and risk angering the worms?"). It all depends on how the code is going to end up structuring itself.
This thread has been an amazing goldmine of really dramatic advances in the modding field (especially thefriendlyhacker's think_counter discovery), and I've been thinking more and more of writing a couple advanced modding guides on the wiki, that would describe various lua functions and such, and specifically some useful aspects of the data structure. I don't have time for that right now what with all my other projects, but it's a thought worth considering.
zaporozhets looses a roaring laughter, fell and terrible!
Musket-Mod has been missing for a week.
zaporozhets has created An Explanation of the Musket-Mod Drama, a mod bone post! It menaces with walls of text and rantings about due credit. He claims it as personal treasure.
Jokes aside, the df community is honestly the best one I've seen yet, and I can prove it. During reddit's circles of trust thing, most circles were composed of closed cliques, while the only requirement to enter the dwarf fortress circle was proof that you play df. We were among the largest circles, twice, before being betrayed by people that I'm pretty sure aren't actual df players. My theory is that it's the learning cliff that scares off most low-quality players, and the ones willing to put in the time to get past it tend to be good people.
I put a thing in the lasgun script that removes the lasers after they've hit, just needs them to be made no_impact_destroy = false. Out of interest did you plan on doing anything in particular with it?
Your theory makes a lot of sense, not to sound judgemental but I've tried explaining Dwarf Fortress to friends who I love dearly, but are by all accounts 'low-quality players' (of phone games and the like), and they just don't seem to grasp the sheer magnitude and unparalleled scope of it or take any interest.
Using a tileset just made it worse, with them fixating on a flashing icon of a horse. ::)
Thanks, seems to work! I'll be using it mostly just for cleanup of shot projectiles; things get really messy once a couple gunners start shooting at flying targets (@*!#^! keas) which has the shot drop to the floor un-destroyed, regardless of the impact_destroy flag. Same thing if they hit a wall that is above the ground. It would also be weird for bullets to be re-usable without needing more gunpowder so I've just had it delete anything starting with ITEM_AMMO_GUN.
For once, I might actually need to get a mod that adds guns. Assuming they can kill reliably.
Some things I was pondering while going over the cannon script: The subtype increment/decrement thing used to rotate it is clever, but its going to cause weirdness if any other mods add a custom building in an alphabetically higher raw file. I'm somewhat stuck on thinking of anything better though, since I can't see to get dfhack to read the damned custom building subtype name. Theres a workaround involving making a separate pair of reactions for the North > West and West > North rotation, but it seems... somewhat ungraceful? I also don't know how it will handle the building subtype changing with reactions still queued, possibly it will keep the old reaction jobs and turn itself into a screw press. It'd be nicer if it could just use the same too jobs and do a check for 'does my subtype name end in '_N' or not'.
local cannonSubtype
dfhack.onStateChange.cannon = function(state)
if state == SC_WORLD_LOADED then
for indx, building in pairs(df.global.world.raws.buildings.all) do --not sure whether to use .all or .workshops
if building.code == "CANNON_N" then
cannonSubtype = indx
end
end
end
end
I also noticed the blunderbuss-missile spawner doesn't copy over ammunition quality, pelletProjectile.item.quality = projectile.item.quality should cure that.
My concern is just on how well they do.
Marksdwarves for me in vanilla have just never been worth the material investment (they piss through ammo at a constant rate, necessitating dedicating at least two or three people just to making ammo for them with just a single full squad,) and lacking killing power, since unless a major artery or the brain is hit, it usually takes forever to kill anything with them. Hell, more than half the time hunters can't kill anything besides small game reliably.
These weapons obviously (and understandably) have an even greater material investment, so I'm a bit leery. But I'll give it a shot.
About the cannons, I've been considering using [PRESERVE_REAGENT] as well as making the barrel used to build the building a container tool item. All I'd have to do to make be 'loaded' is move reagents to the barrel 'container' until there are no empty barrels (relevant for organ guns), and when firing check for any containers with use_mode == 2 (item used as building item) and spew it out until there is no more left.
I actually considered the thing you suggested for indexing the custom workshop subtypes, but found it shouldn't even be needed. All I need to do when turning clockwise is have the workshop check 'Does my name end in _N, _E or _S? then add 1 to subtype' and 'else, substract 3 from subtype'. Basically the same thing you did except it doesn't check against its own subtype but against a string match in the name. Only problem with that is, I've not been able to read anything from the building raws from the building objects (which seem to be different data structures altogether). I'm probably missing something simple...
I might use that index code snippet at some point though, thanks :)
local cannonDirection = string.sub(df.global.world.raws.buildings.all[cannon.custom_type].code, -2)
if job.reaction_name == "ROTATE_CANNON_R" then
if cannonDirection == "_N" or cannonDirection == "_E" or cannonDirection == "_S" then
cannon.custom_type = cannon.custom_type + 1
else
cannon.custom_type = cannon.custom_type - 3
end
else
if cannonDirection == "_E" or cannonDirection == "_S" or cannonDirection == "_W" then
cannon.custom_type = cannon.custom_type - 1
else
cannon.custom_type = cannon.custom_type + 3
end
end
right?Also I hadn't considered masterwork announcement spam. Gah. Does it also announce masterwork if its an existing item changing quality later I wonder?
Edit: dfhack.items.moveToContainer isn't moving to container. No error output either. Is it picky about the sort of container used or does it not like me editing the container property in an existing item? I'll try adding some of the tool use tags and risk dwarves storing plump helmets in gun barrels.
----changes the cooldown between each time a creature fires a projectile weapon----
--author thefriendlyhacker
--based on work by Roses, expwnent, zaporozhets and Putnam.
local usage = [====[
ranged/ranged-rof
===========================
This triggers when a unit fires a projectile, and changes the delay (in ticks) until the unit's
next attack.
The new delay is set according to the following formula:
New Delay = Base Delay + Old Delay * Delay Multiplier
Base delay is set by -delayBase, and Delay Multiplier by -delayMult
For reference, dabbling firers have a normal delay of 80 ticks, legendary +5 firers 48 ticks, and legendary +100 firers 40 ticks.
Several arguments can be added to restrict a particular command to select weapons/ammo (see below)
A set of values can be passed through -delayBase and/or -delayMult. When only one of the args is multi-value, the other is treated as an equal sized set of identical values. If both are multi-value sets, they must be of equal length.
The script steps through the set of values when a unit fires a projectile weapon, and keeps track of
the unit's position in the set on a per command, per weapon basis. Beginning at the first
number in the set, the script iterates through the entire pair of sets, using each pair of numbers
to calculate the delay for a single firing event. Effectively, this allows for variable delay
times. This can simulate, for example, burst fire weapons, multi-barreled firearms, or autoloading
weapons with a reload time.
After a delay (calculated using -resetBase and -resetMult similar to the equation above), the position in a unit's firing delay set is reset to the first position.
Data does not persist across saves, which will mean that loading saves made in the middle of combat will influence that combat when using variable delays. Outside of combat, this shouldn't matter.
Usage::
-name str
name of the command. Not optional.
-clear name (not implemented atm)
unregisters a named command. If arg is used with no name, unregisters every command
-reset name (not implemented atm)
clears all persistant data associated with the named command. If used with no name, clears all data
-reqProjType subtype or [ subtype1 subtype2 ... ]
only runs command if the projectile is one of the appropriate subtypes
example: ITEM_AMMO_BOLTS
-reqWeaponType subtype or [ subtype1 subtype2 ... ]
only runs command if the weapon is of one of the appropriate subtypes
example: ITEM_WEAPON_CROSSBOW
-reqProjMat mat or [ mat1 mat2 ... ]
only runs command if the projectile is one of the appropriate material(s)
examples: INORGANIC:IRON, CREATURE_MAT:DWARF:BRAIN
-reqWeaponMat mat or [ mat1 mat2 ... ]
only runs command if the weapon is one of the appropriate material(s)
same format as -reqProjMat
-timeBase nbr or [ nbr1 nbr2 ... ] (default 0)
-timeMult nbr or [ nbr1 nbr2 ... ](default 0)
timeBase and timeMult are used to set the time until the next attack
at least one must be set, and the number can be negative or non-integer
if they are both multi-element tables, they must be of equal length
-timeBase is a flat number of ticks
-timeMulti is a multiplier of the base firing delay of the unit
see above for details
-neverReset
never resets position in a loop
-resetBase nbr (default 0)
-resetMult nbr (default 5)
determines how long until a unit's position in the command's firing delay set is reset
works similarly to timeBase and timeMult, see above for details
]====]
eventful = require 'plugins.eventful'
utils = require 'utils'
--holds individual commands as anon functions
rangedTriggers=rangedTriggers or {}
--3 dimension sparse table for command/creature/firing weapon combos,
--holds the position of a unit in a command's delay set, on a per weapon basis
rangedArrayPos=rangedArrayPos or {}
--
rangedResetTimeouts=rangedResetTimeouts or {}
eventful.enableEvent(eventful.eventType.UNLOAD,1)
eventful.onUnload.rangedTriggerModule = function()
rangedTriggers = {}
rangedArrayPos = {}
rangedResetTimeouts = {}
end
function eventfulFunc(projectile)
if projectile.distance_flown~=0 then return end
for funcName,func in pairs(rangedTriggers) do
if func(projectile,funcName) then return end
end
end
eventful.onProjItemCheckMovement.rangedTriggerModule = eventfulFunc
function getCommandFunc(reqProjMats,reqProjTypes,reqWeaponMats,reqWeaponTypes, timeBase, timeMult, resetBase, resetMult, neverReset)
return function (proj,funcName)
if not proj.firer then return false end
local weapon=df.item.find(proj.bow_id)
--dismembered limbs require this
if not weapon then return false end
--first off,checks to see if this conforms to the command requirements
local found=false
for _,mat in ipairs(reqProjMats) do
if mat==dfhack.matinfo.decode(proj.item):getToken() then found=true end
end
if #reqProjMats>0 and not found then return false end
found=false
for _,mat in ipairs(reqWeaponMats) do
if mat==dfhack.matinfo.decode(weapon):getToken() then found=true end
end
if #reqWeaponMats>0 and not found then return false end
found=false
if #reqProjTypes>0 and proj.item:getSubtype() ~= -1 then
for _,itype in ipairs(reqProjTypes) do
if dfhack.items.getSubtypeDef(proj.item:getType(),proj.item:getSubtype()).id == itype then
found=true
end
end
end
if #reqProjTypes>0 and not found then return false end
found=false
if #reqWeaponTypes>0 and weapon:getSubtype() ~= -1 then
for _,itype in ipairs(reqWeaponTypes) do
if dfhack.items.getSubtypeDef(weapon:getType(),weapon:getSubtype()).id == itype then
found=true
end
end
end
if #reqWeaponTypes>0 and not found then return false end
--now, do internal stuff, initialize any rangedArrayPos data when necessary and set/reset the delay trigger
local oldThinkCounter=proj.firer.counters.think_counter
if #timeBase>1 then
if not rangedArrayPos[funcName][proj.firer.id] then rangedArrayPos[funcName][proj.firer.id]={} end
if not rangedArrayPos[funcName][proj.firer.id][proj.bow_id] then rangedArrayPos[funcName][proj.firer.id][proj.bow_id]=1 end
if not neverReset then
local delayTime=math.max(1,math.floor(oldThinkCounter*resetMult+resetBase))
if not rangedResetTimeouts[funcName][proj.firer.id] then rangedResetTimeouts[funcName][proj.firer.id]={} end
if rangedResetTimeouts[funcName][proj.firer.id][proj.bow_id] and dfhack.timeout_active(rangedResetTimeouts[funcName][proj.firer.id][proj.bow_id]) then
dfhack.timeout_active(rangedResetTimeouts[funcName][proj.firer.id][proj.bow_id],nil)
end
--these get used later when the projectile has probably been deleted
--hence the need to store locally so we don't have dangling references causing segfaults
local pid=proj.firer.id
local bowid=proj.bow_id
rangedResetTimeouts[funcName][pid][bowid]=dfhack.timeout(delayTime,'ticks',function() rangedArrayPos[funcName][pid][bowid]=1 end)
end
end
--now the meaty bit - calculate and set the new think_counter time
if #timeBase>1 then
proj.firer.counters.think_counter=math.max(1,math.floor(oldThinkCounter*timeMult[rangedArrayPos[funcName][proj.firer.id][proj.bow_id]]+timeBase[rangedArrayPos[funcName][proj.firer.id][proj.bow_id]]))
else
proj.firer.counters.think_counter=math.max(1,math.floor(oldThinkCounter*timeMult[1]+timeBase[1]))
end
--iterate through the array of times
if #timeBase>1 then
rangedArrayPos[funcName][proj.firer.id][proj.bow_id]=rangedArrayPos[funcName][proj.firer.id][proj.bow_id]+1
if rangedArrayPos[funcName][proj.firer.id][proj.bow_id]>#timeBase then
rangedArrayPos[funcName][proj.firer.id][proj.bow_id]=1
end
end
return true
end
end
local validArgs = utils.invert({
'help',
'clear',
'reset',
'name',
'reqProjMat',
'reqProjType',
'reqWeaponMat',
'reqWeaponType',
'timeBase',
'timeMult',
'neverReset',
'delayBase',
'delayMult'
})
if moduleMode then return end
local args = utils.processArgs({...}, validArgs)
if args.help then
print(usage)
return
end
if args.clear then
return --todo, code below won't work
--rangedTriggers[args.clear]=nil
--rangedArrayPos[args.clear]=nil
--if dfhack.timeoutActive(rangedDelayedReset[args.clear]) then
-- dfhack.timeoutActive(rangedDelayedReset[args.clear],nil)
--end
end
if args.reset then
return --todo
end
local reqProjMats={}
local reqProjTypes={}
local reqWeaponMats={}
local reqWeaponTypes={}
local timeBase={0}
local timeMult={0}
local resetBase=0
local resetMult=5
local neverReset=false
if type(args.reqProjMat)=='string' then
reqProjMats={args.reqProjMat}
elseif type(args.reqProjMat)=='table' then
reqProjMats=args.reqProjMat
end
if type(args.reqProjType)=='string' then
reqProjTypes={args.reqProjType}
elseif type(args.reqProjType)=='table' then
reqProjTypes=args.reqProjType
end
if type(args.reqWeaponMat)=='string' then
reqWeaponMats={args.reqWeaponMat}
elseif type(args.reqWeaponMat)=='table' then
reqWeaponMats=args.reqWeaponsMat
end
if type(args.reqWeaponType)=='string' then
reqWeaponTypes={args.reqWeaponType}
elseif type(args.reqWeaponType)=='table' then
reqWeaponTypes=args.reqWeaponType
end
if not args.timeBase and not args.timeMult then
error("-timeBase or -timeMult must be defined")
end
if args.timeBase and type(args.timeBase)=='string' then
timeBase={args.timeBase}
elseif args.timeBase then
timeBase=args.timeBase
end
if args.timeMult and type(args.timeMult)=='string' then
timeMult={args.timeMult}
elseif args.timeMult then
timeMult=args.timeMult
end
for i,numb in ipairs(timeBase) do
timeBase[i]=tonumber(numb)
if not timeBase[i] then
error("all elements of timeBase must be numbers")
end
end
for i,numb in ipairs(timeMult) do
timeMult[i]=tonumber(numb)
if not timeMult[i] then
error("all elements of timeMult must be numbers")
end
end
if #timeBase>1 and #timeMult>1 and #timeBase~=#timeMult then
error("-timeBase and -timeMult must be the same length when they are both tables")
end
if #timeBase>1 and #timeMult==1 then
for i=#timeMult+1,#timeBase do
timeMult[i]=timeMult[1]
end
end
if #timeMult>1 and #timeBase==1 then
for i=#timeBase+1,#timeMult do
timeBase[i]=timeBase[1]
end
end
if args.resetBase then
resetBase=tonumber(args.resetBase)
if not resetBase then error("resetBase must be a number") end
end
if args.resetMult then
resetMult=tonumber(args.resetMult)
if not resetMult then error("resetMult must be a number") end
end
if args.neverReset then
neverReset=true
end
if not args.name then error("-name must be specified") end
rangedTriggers[args.name]=getCommandFunc(reqProjMats,reqProjTypes,reqWeaponMats,reqWeaponTypes, timeBase, timeMult, resetBase, resetMult, neverReset)
rangedArrayPos[args.name]={}
rangedResetTimeouts[args.name]={}
I *think* it works without any issues, but I wouldn't be surprised if I screwed something up somewhere, so test it and tell me how it goes. Also tell me if the documentation is understandable - my technical writing skills are mediocre at best.I have been playing around with something lately, and I have just gotten it to a basically functional point (although I will revisit it later and add/tweak a few things). I figured that in the meantime you might like to have it for some double barrel muskets or something.Code: [Select]I *think* it works without any issues, but I wouldn't be surprised if I screwed something up somewhere, so test it and tell me how it goes. Also tell me if the documentation is understandable - my technical writing skills are mediocre at best.
Of course, anyone else is welcome to use it as well if they want to.
...Ah, so I was blind. Good to know.
All I can contribute is df.item.find(item_id)...
...and you can get persistence by hijacking a (hopefully) unused field in the bow if there is one.Ehhh, I don't particularly like the idea of sticking data in random bits of apparently currently hopefully unused memory. It just reeks of "this will bite me in the ass later in excitingly exotic ways". Not to mention the fact that I have several bits of data I need to keep track of, and I would need to change the script logic to remove the "each weapon+firer+command combo has it's own data" stuff (and deal with a bunch of edge cases I avoided by using the current logic), and I intend to add some other scripts of a similar nature at a later date, so I am going to need to hijack a lot of unused memory.
...
Ehhh, I don't particularly like the idea of sticking data in random bits of apparently currently hopefully unused memory. It just reeks of "this will bite me in the ass later in excitingly exotic ways". Not to mention the fact that I have several bits of data I need to keep track of, and I would need to change the script logic to remove the "each weapon+firer+command combo has it's own data" stuff (and deal with a bunch of edge cases I avoided by using the current logic), and I intend to add some other scripts of a similar nature at a later date, so I am going to need to hijack a lot of unused memory.
With all that, it is probably easier in the long run to take the rather weird data structures provided by dfhack's existing persistent storage lua interface (read:paper thin wrapper over some internal DF data structure that dfhack commandeered), write a wrapper that treats each entry as a linked list element with a flag for type, and then go swap out the current table based implementation with a persistent linked list version that is virtually identical logic wise besides some code to restart lost timeout calls, and maybe deleting unneeded tables/linked lists when calling the delayed reset function to minimize the potential accumulation of several megabytes of memory/hard disk overhead in a long running fort. The only serious piece of coding I would need to do is the wrapper itself, and the difficulty in that will stem from me being fairly unfamiliar with Lua more than anything else.
All this will come later, though. For the moment, I am going to stress test what I have already by adding script calls for most of Fallout Equestria's firearms, mod in a reaction to create SMGs, and maybe mod in another reaction to duct tape two SMGs to a chainsaw glaive for funsies and maximum firepower (I shall call it a storm glaive, and it shall be glorious).
Seeing that gif: could I please have randomized lightning strikes when it rains ingame, pretty please? ;)
I was looking into the possibility of making a civ that would use these weapons, but it seems like right now if i gave them the weapons they would make them out of whatever materials they wanted (including wood, I think.) unless I only gave them steel for everything, which i really don't want to do. I know for a fact that the guns work perfectly fine as any material, all the reactions and scripts are already fine with anything.
I'm not worried about balance issues, a copper musket will be much less effective in caving in someone's head than a steel one would, and the steel musket's bayonet would be considerably sharper. I just don't want there to be a situation where the player would go "Why can they make guns out of anything, and I can't?"
Ideally i would just let the player make anything to compensate for the fact I have no control over what other civs make their guns out of. I would have just done that myself instead of complaining here if I knew of any way to have the custom workshop allow any metal in a reasonable way that doesn't involve making a custom reaction for every single metal, or letting dwarves pick whatever metal they want - forcing the player to mess with stockpiles to force a specific material.
I was looking into the possibility of making a civ that would use these weapons, but it seems like right now if i gave them the weapons they would make them out of whatever materials they wanted (including wood, I think.) unless I only gave them steel for everything, which i really don't want to do. I know for a fact that the guns work perfectly fine as any material, all the reactions and scripts are already fine with anything.Here is an idea you could try that is a little hacky but that gets the job done. Add a tool called a "firearm components" or whatever, and another called a "heavy firearm components". Make six custom reactions (copper,bronze, bismuth bronze, iron, steel, candy) per component, with 1 bar for normal components and two bars for heavy parts, and then use one of those components in the making of each firearm, taking the component item's metal as the product weapon's metal. That will let the player use whatever weapon metal materials they want without bloating workshop menus with dozens of custom reactions.
I'm not worried about balance issues, a copper musket will be much less effective in caving in someone's head than a steel one would, and the steel musket's bayonet would be considerably sharper. I just don't want there to be a situation where the player would go "Why can they make guns out of anything, and I can't?"
Ideally i would just let the player make anything to compensate for the fact I have no control over what other civs make their guns out of. I would have just done that myself instead of complaining here if I knew of any way to have the custom workshop allow any metal in a reasonable way that doesn't involve making a custom reaction for every single metal, or letting dwarves pick whatever metal they want - forcing the player to mess with stockpiles to force a specific material.
More on topic, I've added damage falloff, dfhack command line weapon/ammo property population and various other stuffs to the ranged weapon script and gave up on trying to get items in a workshop into a container that is a building item in that workshop and just went went 'delete them and spawn a new one'. It's simple not possible to get the !@#&^!( things out of the workshop through any of the stock DFhack or vmethod functions, best I managed to do was weirdly making them exist both in the workshop and on the floor at the same time which didn't help. Dropping them from a height worked but I'd have to do some weird timeout thing and get it to be smart about finding a place to drop from aaand... none of that is any more graceful than just duping the items, copying the itemquality and deleting the obstinate buggers in the workshop.
Job/reaction triggers also have the same problem as onUnitAttack in that they run just after or before the thing I want to modify exists. (job time in this case, I want to make firing the cannon not take forever).
The damage falloff right now just modifies velocity every 4 tiles of distance flown by something below 1 (or above 1 if your making a rocket or something). Its a bit crude and I might replace that with table that stores per-projectile properties (also handy for smoke, on-impact effects and preventing dumb stuff like smoke being triggered on bullets dropping after they ran out of reach), but it does work nicely for making gunpowder smallarms only go through armor at closer ranges, which was what they were known to do in the middle ages.
Dropping items from a height would in theory work and tried what your suggested, but the item only gets removed from the building holder list once it starts dropping, which is at least 1 tick so you would have to teleport it, use a timeout to wait for it to actually start dropping and then teleport it where you need it. Small bonus might be that it will already be a projectile at that point, so you might only have to change origin/target positions. Its... both kinda janky, so take your preferred pick :)
I should mention that moveToGround and then immediately moving it to container worked at some point when I set the move coords to 5,5,5 but it only worked on one map and I havn't been able to reproduce that. It was weird.
The way I'm having the reactions go faster now is by adding every initiated artillery job to a table, checking job.completion_timer every 50 ticks, doing nothing if its -1 (default state if no dwarf is working the job yet), to 80 if no target is found and to 0 if one is found as well as dropping the job from the table. Using completion_timer seems to have no downsides and doesn't have issues like gunners gaining skill from having commands cancelled, dwarves finding no targets will just wait for something to blast until the job is cancelled or presumably until the dwarf gets sick of it due to starvation/etc. The only issue I'm having is that the script seems to have trouble identifying a firer every now and then.
I should also add that onJobInitiated triggers once the player orders up the job, immediately checking for a firer to modify results in the script borking because it doesn't have a firer yet.
The trick I'm using right now for artillery dwarves getting spooked and running off is kinda dumb to be honest, I just make the front facing workshop tiles non-passable. It makes some amount of sense for medieval guns which were often placed behind wooden barricades, what with them often being set up in range of crossbows and other small weapons. I've not really tested it extensively though, my reserve solution was making the operator blind. Can't be spooked by things you can't see and blind dwarves don't really seem impeded in doing jobs. NOFEAR might work too, though it might result in typical dwarf behaviour of leaving the gun to charge and hit them with a sock.
I'm having some issues with the tables still, I'll post it when everything is behaving as desired. Right now it works as long as there are a few guns all neatly completing their reactions, but it breaks once you spam a bunch of reactions (table becomes too large and complains about running out of memory) and when reactions are cancelled (the table entry will linger), I'll have to find a better way to check whether jobs are dead than just completion_timer being 0 and not store the entire job and building entry in the table (just the IDs instead and only looking up the actual job/building/units once the job is under way). I havn't noticed any effect on performance, but I've only let the timeout check the table every 50 ticks so it only does a single check on the job timer per job per 50 ticks, which isn't really a massive burden as long as the table doesn't become polluted with lingering rubbish.
I'm currently in the process of moving though so the next few days will be somewhat less productive for me.
Also yes, that last sentence would make an interesting out of context quote :)
Really quick question, would copy-pasting the override stuff into a separate download of Meph's tileset break anything? I have absolutely no idea how graphic-related stuff works beyond some very bare-bones work I've started, and I'd love to have my engineering sector have just a bit more bite to it than a siegeworks and a couple mechanic workshops, and I don't wanna go just copy-pasting the override.txt into a fresh install of the tileset.
[TILESET:musketmod.png:musketmod.png:musketmod_overrides]
[OVERRIDE:228:I:TRAPCOMP:TRAPCOMP:0:musketmod_overrides:83] - cannonball
It is indeed due to updates to the main tileset (of which I suspect another might be coming soon, but I'd have to ask Meph to confirm.) He asked me to show off the tileset, and I figured I'd go ahead and add a few other mods mainly to spice things up, since just a boring old building fort isn't really my style - I'm a war-mongering jackass after all, and I figure I can use it as an opportunity to tell a good story and use the tileset to make a fort that looks damned good while doing it. ;D
Besides, tell me that copper set isn't begging to be a building for a gunsmith.
I haven't actually used it yet though, unfortunately. Been fiddling around with a whole bunch of other stuff, both mods and not, as well as chipping away at graphics for ZM5's cavern and biome mods, which is... Well, even if I weren't drawing for money or playing games alongside everything else, it's still gonna be a herculean task just in terms of number of things. But I'm genning up a world with the musket mod right now, mainly to see it in action alongside bug-testing stuff of my own.
I really don't envy you taking that on, I had a look at your announcement and I'm impressed, those things look f*cking twisted (in the nicest possible way) but it seems like a lot of work, be careful not to burn yourself out. I especially like the Flesh Harvester, it's a cutie!
Believe it or not, if I can manage to make the place look like a blasted hellscape without having to pumpstack up magma, whichr equires learning how to even do that, I'll consider it a win. I'll just need to be careful to not use rockets and the like while the infantry are beyond the defenses. ;)
Yeah, well, I figure since I can't really afford to pay someone and happen to have some drawing ability, might as well make them more accessible by including graphics, right? And that'd be on ZM5, he's the one who gave them purple-ish skin. :P
I found mismatch.
tesla gun's token names are not same.
in reaction.txt ,
[PRODUCT:100:1:WEAPON:ITEM_WEAPON_GUN_LIGHTNINGGUN:GET_MATERIAL_FROM_REAGENT:B:NONE]
in weapon.txt ,
[ITEM_WEAPON:ITEM_WEAPON_GUN_TESLAGUN]
Hey, nice work on the firearms! Would you mind if I make a compatibility patch between your mod and mine?
Also, in [REACTION:CANNONBALL], a closing bracket is missing in the line [CATEGORY_PARENT:FORGE_AMMO
Nothing cruicial, but the workshop category will probably not work properly.
Sver, of course you can.
Can I be straightforward and ask if you're simply being lovely in asking or are genuinely unsure, a few people have asked and I'm worried I've not made it clear enough in the OP that I'm happy for this stuff to be used for whatever. Maybe everyone is just being nice and polite.
Oh, well, it's just that the head post talks specifically about scripts (which will not conflict with my mod in any way - I'm only modifying the raws), and I'm generally wary of straightaway including a huge chunk of someone else's work into my own upload, even with some changes applied.
I mean, it probably wouldn't hurt to specify that the raws are ok to use/modify too - if that's what you want. Then, some people may still be wary or just polite, but wha' can do about it :)
Oh god, does this mean I could end up accidentally knocking down trees and walls if I get careless? I mean, if so, that's grand, just because you proved it was doable.
Could you clarify a bit on the exact mechanics of the blunderbuss and the dragon pistol? Do the split shots retain the force and velocity of the weapon or is it uncertain?I took a gander at the code, and if I understand correctly the code just changes the fired projectile to a pellet, creates duplicates of the projectile a few times, makes a projectile out of each of the duplicates, copies the projectile properties over and adds a random factor to the origin and destination tiles. As such, the velocity and material of each pellet will be identical to the fired projectile.
I took a gander at the code, and if I understand correctly the code just changes the fired projectile to a pellet, creates duplicates of the projectile a few times, makes a projectile out of each of the duplicates, copies the projectile properties over and adds a random factor to the origin and destination tiles. As such, the velocity and material of each pellet will be identical to the fired projectile.
Previously, I was plinking completed jobs from the linked list along with setting the timer to 0 in the case of firing jobs, but that did not cover cases where the job was not completed but still expired like the player canceling or the operator/building meeting some untimely demise. In that case the job would linger in the linked list and eventually return bogus values before giving a memory error. This prompted me to try and write a check to see if a job went gone on its own, but nothing I've found really works to that effect.
So, instead I'll just not use a link table and store only the job id, look for it on each iteration and drop the job id if its not found. Least, that's the plan. My new place is short on internet connection which makes it somewhat of a pain to check general lua docs, forums, etc.
If that also fails I might just have to rip off your job checker and not store jobs anywhere at all :)
Anyhow, nice going on the other improvements and fixes! Hadn't noticed the bork in the targeting, I was mostly just testing the cannon by shooting it at my own dwarves with a firer added to the cannon projectile, which prevents any kind of friendly fire (boring, but convenient for testing. Also a temporary requirement of my projectile modding script, should have that fixed soon).
If only the AI could bring guns and use them intelligently, could make turtling fortress a suicidal tactic.
You need to point the firer to the unit working the job first, else it'll try and copy a nothing. I thought not having a firer was intentional though, since it creates hilarious friendly fire incidents :)
Those testers had to be some of the worst shots in dwarven history.
Appreciated your new tile-destructive rocket launcher - to impressive, although I find that such weapons are not hand-carried.
You could not add something like thunderflash or dinamite, which was activated by a lever and also destroys tiles? - solely for engineering tasks).
I do like the idea of lever activated explosives though if doable. Short on miners? Have an engineer clear the space with a couple charges and some mechanisms. Need to deal with a particularly nasty critter? Lure it into a room filled with satchel charges and hit the lever. Need to burn stuff off above or below ground? Rig up a fire bomb to start a fire and away you go at the flip of a lever, suddenly free of all that tangled greenery (or even use such a thing to incinerate corpses without magma.)
Is there a convenient entity file lying around?
I'm an idiot, I didn't realize gas cannister liquids had to have the [SYN_CONTACT[ or [SYN_INHALED] tags for them to have any effect. Makes chemical weapons pretty useless when used with almost all of the native liquids.About this...Since modding stone boiling points post-embark works, I wonder whether temporarily tagging the syndromes with that in df.global.world.raws on explosion would work.
I guess I'll eventually have to try and add some raws for new ones and a maybe a laboratory to make them in. There are plenty of effects to choose from, but deciding on names and reagents will be difficult.
Alright, I got something presentable at last for both the ranged weapon script and the artillery script. Both are working as intended, I even got the organ gun to work satisfying. I ended up snubbing the job completion trigger entirely and just faking work completion timers with a timeout command, which lets me do some neat stuff like leading each organ gun barrel one by one with only one job set to repeat. It fetches some fairly basic properties per artillery type now, like rate of fire for multibarrel guns and reload times. It bases hitrate and reload rate on firer skill, a shoot force property the works exactly the same as vanilla ranged weapons and lets ranged-mod handle the remaining stuff like smoke and piercing effects. I still want to expand it a bit more to let me load them with stacks of ammunition rather than single items and add let the repeat jobs increase experience properly (and let botched job like a fire command that finds no ammo to fire NOT generate experience), but right now both scripts work well enough to let me finally update my main mod.
Pasties for ranged-mod and arty-mod respectively, more details in their -usage sections: https://pastebin.com/VZ0M5F6T https://pastebin.com/bq9kutS9
And a topic in the utils subforum: http://www.bay12forums.com/smf/index.php?topic=172239
About this...Since modding stone boiling points post-embark works, I wonder whether temporarily tagging the syndromes with that in df.global.world.raws on explosion would work.
Though one may consider it undesirable.
Heh, fun fact. I am also in the progress of writing a general purpose set of ranged scripts. They have a shared back end that controls their ordering and passes tags between them so the individual scripts can communicate to each other. It is still a WIP, but at the moment I have implemented variable rates of fire for hand-held projectile weapons (and it is done in a way that can mimic magazine fed weapons) and multi-shot projectiles. All I have to do is write a third script that alters velocity (which should be easy) and I can replace all the glob projectile interaction based weapons in my mod with real bullets.Alright, I got something presentable at last for both the ranged weapon script and the artillery script.I had a quick look when it released and was very impressed with all the stuff you added (I'll need to take another look for the pseudo-completion timer stuff which I missed).
...
Wish I had the intelligence to make (or even use) modtool-style scripts but I find them very confusing to work with.
Not had much time to play with it in game yet though which is a shame, looking forward to seeing the organ gun in action.
I can probably answer that one.About this...Since modding stone boiling points post-embark works, I wonder whether temporarily tagging the syndromes with that in df.global.world.raws on explosion would work....
Though one may consider it undesirable.
Your way would be far superior, not sure why one might consider it undesirable given it could presumably be changed back after the bang, you might have to explain your thinking on that one.
Hey, excuse me for a possibly stupid question, but does this mod work nicely with Adventure Mode? I mean, will Blunderbusses shoot in a cone and Machine Guns have short reload times, etc?
Can you add tilesets that work properly with this mod?
Or, can you teach how to make tileset to support this mod?
Hey, excuse me for a possibly stupid question, but does this mod work nicely with Adventure Mode? I mean, will Blunderbusses shoot in a cone and Machine Guns have short reload times, etc?
No such thing as a stupid question, nothing was made with adventure mode in mind and so there are many oddities, but as best I can tell all the weapons still function properly they just don't look nearly as cool.
For example the lightning gun is one of the most script heavy weapons and whilst it works, you'll only see the lightning briefly if at all due to the differences in timescale between fortress and adventure modes.
I'd only recommend it if you really really want guns, your mileage may vary.Can you add tilesets that work properly with this mod?
Or, can you teach how to make tileset to support this mod?
Sure, what tileset did you want me to add?
If you want to make a tileset work yourself, you'll want to navigate to "Dwarf Fortress/data/init/overrides.txt" and add:after the other tileset definitions (lines beginning with [TILESET:).Spoiler (click to show/hide)
Then you'll want to add:Somewhere with the other overrides (not sure it matters where).Spoiler (click to show/hide)
Oh, thanks for kind instruction. :D
Sorry for my insufficient explanation.
But i mean,
In readme file, it said this mod works only in ascii or meph graphic set.
Can i make it change to works with other graphic set?
I had played in ascii version but now i want to change graphic to spacefox.
--if pellet is created midair then dfhack "helpfully" makes it a falling projectile
--this prevents the above call from creating a projectile, so we need to "borrow" the one dfhack made
if pelletProjectile==nil then
local projLink=df.global.world.proj_list
repeat
projLink=projLink.next
if projLink~=nil then
if projLink.item.item==pellet then
pelletProjectile=projLink.item
end
else error("error - cannot create projectile from new item for unknown reason") end
until pelletProjectile
end
I noticed that you don't manually init every part of the created projectile, so you may want to go through and check that there isn't anything weird left over from the old falling projectile your code is overwriting. Otherwise, the above snippet should fix the bug.Oh, thanks for kind instruction. :D
Sorry for my insufficient explanation.
But i mean,
In readme file, it said this mod works only in ascii or meph graphic set.
Can i make it change to works with other graphic set?
I had played in ascii version but now i want to change graphic to spacefox.
The problem is that the tileset included with the mod is at 32x32 resolution, whereas spacefox is 16x16.
You could try simply halving the resolution, but I had a quick go in GIMP and it looks pretty bad without retouching everything.
Ideally new graphics would need to be drawn for everything at that resolution, but I'm no artist and I'm finding free time a little hard to come by ATM to even make something as paltry as my ability would allow.
Sorry I can't be more help, I do want to add compatibility for smaller tilesets at some point.
Bump, because I'd really like to see a v1 version of this.I appreciate it.
This looks wonderful!Bump, because I'd really like to see a v1 version of this.I appreciate it.
Recently started working on this again after a leave of absence. Currently completely redoing the wall-breaching/destruction system; explosions now have better z-level support, they are now spherical rather than squared, and can be of any size/height. They now use raycasting rather than instantaneously coming into existence in their entirety, meaning that if a wall withstands a blast, anything behind the wall will survive it.
On a more technical note, some methods are finally being moved to a shared-functionality utility module, meaning less code repetition and easier to read scripts for modders.
Proper blast mining is next on the table, but I've also been thinking a lot about changing the way weapons are constructed, requiring additional tool components (maybe something like 'small mechanisms' or just 'barrels'), but ultimately allowing them to be made of either wood or metal, as thefriendlyhacker suggested back in September. This will solve the current material problems with allowing the other civs access to the guns.
Got some future features planned, but I want to keep them under wraps until I figure out if I can actually manage it, it'll also be necessary to have an easier way for people to disable the parts of the mod they don't like or don't think fit the setting of their game.
Edit:
Making progress on terrain destruction. Had some problems with the explosion algorithm when the terrain destruction parameter was set, with there being 5 seconds per explosion where the game would be frozen, but I've been working on optimizing it where I'm able.
The whole thing is now taking between ~0.01 and ~0.06 seconds for a small 3*3*3 explosion and between ~0.09 and ~0.12 seconds for a larger 5*5*7 one.
(https://i.imgur.com/IIhGg1i.gif)
local utils = require("utils")
local function explode(pos, intensity, incendiary)
-- what you have been working on
end
if #{...} == 0 then return explode end
local validArgs = utils.invert({
"position", -- DF position
"intensity", -- float
"incendiary" -- bool
})
local args = utils.processArgs({...}, validArgs)
if not args.position then
qerror("Position not specified!")
end
local pos = {x = tonumber(args.position[1]), y = tonumber(args.position[2]), z = tonumber(args.position[3])}
if not dfhack.maps.isValidTilePos(pos) then
qerror("Invalid position!")
end
if not args.intensity then
qerror("Explosion intensity not specified!")
end
explode(pos, args.intensity, args.incendiary)
which is based on "modtools/create-unit"
How did I miss this... The firearms mod... It is fantastic!
The lack of proper ranged weapons is what made it hard for me to develop the "Fallout" total conversion mod in the past. This looks just fantastic, I will definitely look into it.
One simple question: what is your opinion on taking your mod, changing gun values and using them in a separate mod/total conversion? With full credit given.
I had thoughts about bringing DF Fallout back for a while now. Would you allow that?
How did I miss this... The firearms mod... It is fantastic!
The lack of proper ranged weapons is what made it hard for me to develop the "Fallout" total conversion mod in the past. This looks just fantastic, I will definitely look into it.
One simple question: what is your opinion on taking your mod, changing gun values and using them in a separate mod/total conversion? With full credit given.
I had thoughts about bringing DF Fallout back for a while now. Would you allow that?
Bit of a necro since the creator hasn't been online since the beginning of the global pandemic (2020) mind you, but this thread really is great. Im sure they'd probably impart their blessing if you were responsible with it, in any case there are supplimentary credits on the OP you could add commented out in any sort of personal published adjustment.
I especially like normal period or fantasy weapons with the smoke as a really well thought out touch to make the modded experience more novel. Or the idea that putting your spotter dogs over your walls might leave them open to grenadiers inadventently blowing apart your structures meaning you have to replace it with metal out of practicality. Its been on my list of things to poke at, but i struggle with finding niches to stick it in then sticking to seeing it through to the end.
Do you make it in free time whenever, or do you have an approximate ETA when you plan to release it?
I won't rush the mod I am working on, so it will take a while. If you are around with more ideas/extensions to the system, I could use either if you also give a permission.
I'm back at it, and currently I foresee hours of trying to balance "a pistol" vs "a rifle" vs "a typical armor" :D.
The best part of THIS mod is ability to change the shooting rate of guns. It is something that always made melee better.
I do notice an issue though. no matter how I torture Evenful, the lodged in bullets do not disappear, and they are pulled out and dropped on the floor.Shucks.