Last active
December 11, 2017 20:37
-
-
Save Putnam3145/2d1609e935f91f2e50371c9787914b6b to your computer and use it in GitHub Desktop.
Allows the addition of custom artifacts with arbitrary name, mat and type to the world in Dwarf Fortress.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Makes it so that the world will always have certain artifacts in certain sites when world loads. | |
--@ module = true | |
--Author Putnam | |
local usage = [===[ | |
modtools/custom-artifact | |
===================== | |
This tool, when run, checks if the specific item has an artifact record somewhere in the world | |
and places the artifact at a valid site (which can be constrained by arguments) if it is not found. | |
Arguments:: | |
-itemType type | |
the type of item that will have an artifact spawned | |
examples: | |
WEAPON:ITEM_WEAPON_PICK | |
RING | |
-itemMat mat | |
the material of the newly generated item | |
examples: | |
INORGANIC:IRON | |
CREATURE_MAT:DWARF:BRAIN | |
PLANT_MAT:MUSHROOM_HELMET_PLUMP:DRINK | |
-name name | |
the item's name | |
should be set, will just go with no name if not | |
-amount num | |
the minimum artifacts required | |
will continue to create new artifacts until this amount is reached | |
this argument is optional and will default to 1 | |
-ignoreExisting | |
will create (num) artifacts named (name) regardless of existing artifacts of that type | |
do not use in onload scripts, will overrun world with that artifact type given enough reloads | |
-specificEntityType [ entity1 entity2 ... ] | |
entity filter, will only spawn in these entity's sites | |
examples: | |
MOUNTAIN | |
EVIL | |
FOREST | |
PLAINS | |
-specificSiteType [ site1 site2 ... ] | |
site filter, will only spawn in these site types | |
examples: | |
CAVE_DETAILED | |
DARK_FORTRESS | |
TREE_CITY | |
CITY | |
-help | |
displays this message | |
]===] | |
local utils=require('utils') | |
validArgs = utils.invert({ | |
'itemType', | |
'amount', | |
'itemMat', | |
'specificEntityType', | |
'specificSiteType', | |
'ignoreExisting', | |
'name', | |
'help' | |
}) | |
function getItemType(item) --just kinda grabbed this from item-trigger, like the help dialogue above | |
local itemType | |
if item:getSubtype() ~= -1 and dfhack.items.getSubtypeDef(item:getType(),item:getSubtype()) then | |
itemType = df.item_type[item:getType()]..':'..dfhack.items.getSubtypeDef(item:getType(),item:getSubtype()).id | |
else | |
itemType = df.item_type[item:getType()] | |
end | |
return itemType | |
end | |
function mysplit(inputstr, sep) --https://stackoverflow.com/questions/1426954/split-string-in-lua | |
if sep == nil then | |
sep = "%s" | |
end | |
local t={} ; i=1 | |
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do | |
t[i] = str | |
i = i + 1 | |
end | |
return t | |
end | |
local function findTranslation(str) | |
for k,v in ipairs(df.global.world.raws.language.translations) do | |
if v.name==str then return k,v end | |
end | |
return false | |
end | |
function createArtifact(itemType,itemSubtype,name,material,entityFilter,siteFilter) | |
local newArtifact = df.artifact_record:new() | |
newArtifact.id=df.global.artifact_next_id | |
local rng=dfhack.random.new(os.time(),df.global.artifact_next_id) | |
local eligibleSites={} | |
for _,site in ipairs(df.global.world.world_data.sites) do | |
if site.civ_id~=-1 then | |
local thisSiteType=df.site_type[site.type] | |
if thisSiteType and (not entityFilter or entityFilter[df.historical_entity.find(site.civ_id).entity_raw.code]) and (not siteFilter or siteFilter[thisSiteType]) then | |
table.insert(eligibleSites,site.id) | |
end | |
end | |
end | |
local pickedSite=eligibleSites[rng:random(#eligibleSites)+1] | |
newArtifact.anon_1=-1000000 --TODO: REPLACE REPLACE REPLACE REPLACE REPLACE ALL OF THESE ANON IS BAD | |
newArtifact.anon_2=-1000000 | |
newArtifact.anon_3=-1000000 | |
newArtifact.anon_4=pickedSite | |
newArtifact.anon_5=1 | |
newArtifact.anon_6=-1 | |
newArtifact.anon_7=-1 | |
newArtifact.anon_8=-1 | |
newArtifact.anon_12=pickedSite | |
newArtifact.anon_13=1 | |
newArtifact.anon_14=-1 | |
newArtifact.anon_15=-1 | |
newArtifact.anon_16=-1 | |
newArtifact.anon_17=250 | |
newArtifact.anon_18=0 | |
newArtifact.anon_19=3 | |
if name then | |
newArtifact.name.has_name=true | |
newArtifact.name.first_name=name | |
end | |
local newUnit = df.unit:new() --temp boi | |
newUnit.pos.x=df.global.world.units.active[0].pos.x | |
newUnit.pos.y=df.global.world.units.active[0].pos.y | |
newUnit.pos.z=df.global.world.units.active[0].pos.z | |
local newItem = df.item.find(dfhack.items.createItem(itemType,itemSubtype,material.type,material.index,newUnit)) | |
newUnit:delete() | |
newUnit=nil | |
newItem.id=df.global.item_next_id | |
newItem.pos.x=-30000 | |
newItem.pos.y=-30000 | |
newItem.pos.z=-30000 | |
local artifactRef=df.general_ref_is_artifactst:new() | |
artifactRef.artifact_id=newArtifact.id | |
newItem.general_refs:insert('#',artifactRef) | |
newItem.flags.artifact=true | |
newItem.flags.artifact_mood=true | |
newItem.maker=-1 | |
newItem.masterpiece_event=-1 | |
newItem.quality=df.item_quality.Artifact | |
newArtifact.item=newItem | |
local newEvent=df.history_event_artifact_storedst:new() | |
newEvent.artifact=newArtifact.id | |
newEvent.unit=-1 | |
newEvent.histfig=-1 | |
newEvent.site=pickedSite | |
df.global.world.history.events:insert('#',newEvent) | |
df.global.world.artifacts.all:insert('#',newArtifact) | |
df.world_site.find(pickedSite).artifacts:insert('#',newArtifact) | |
df.global.artifact_next_id=df.global.artifact_next_id+1 | |
end | |
if moduleMode then | |
return | |
end | |
local args = utils.processArgs({...}, validArgs) | |
if args.help or not args.itemType or not args.itemMat then | |
print(usage) | |
return | |
end | |
local itemType,itemSubtype | |
local itemTypeSplit=mysplit(args.itemType,':') | |
local itemTypeStr,itemSubtypeStr=itemTypeSplit[1],itemTypeSplit[2] | |
itemType=df.item_type[itemTypeStr] | |
if not itemType then | |
qerror('Could not find item type: '..args.itemType) | |
end | |
if #itemTypeSplit>1 then | |
local temp | |
for _,itemdef in ipairs(df.global.world.raws.itemdefs.all) do | |
if itemdef.id == itemSubtypeStr then | |
itemSubtype=itemdef.subtype | |
break | |
end | |
end | |
if not itemSubtype then | |
qerror('Could not find item type: '..args.itemType) | |
end | |
end | |
args.amount=args.amount and tonumber(args.amount) or 1 | |
local totalArtifactsOfItemType=0 | |
if not args.ignoreExisting then | |
for k,v in ipairs(df.global.world.artifacts.all) do | |
if getItemType(v.item)==args.itemType then | |
totalArtifactsOfItemType=totalArtifactsOfItemType+1 | |
end | |
end | |
end | |
local itemMat=args.itemMat and dfhack.matinfo.find(args.itemMat) or false | |
if totalArtifactsOfItemType<args.amount then | |
for i=totalArtifactsOfItemType,args.amount-1,1 do | |
createArtifact(itemType,itemSubtype,args.name,itemMat,args.specificEntityType and utils.invert(args.specificEntityType),args.specificSiteType and utils.invert(args.specificSiteType)) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment