Skip to content

Instantly share code, notes, and snippets.

@Putnam3145
Created October 17, 2013 09:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Putnam3145/7021850 to your computer and use it in GitHub Desktop.
Save Putnam3145/7021850 to your computer and use it in GitHub Desktop.
Eh, might as well. It's got some interesting fusion code.
local function getSuperSaiyanLevel(saiyan)
--15 is combathardness
if df.creature_raw.find(saiyan.race).creature_id~="SAIYAN" then return 0 end
local combatHardness=dfhack.units.getMiscTrait(saiyan,15,true).value --creates the misc trait if the saiyan doesn't have it yet
return (combatHardness>99) and 3 or (combatHardness>64) and 2 or (combatHardness>31) and 1 or 0 --return (x>y) and x or y is syntactically equivalent to, say, z = (x>y) : x ? y; return z; in C++.
end
local function superSaiyanGodSyndrome()
for syn_id,syndrome in ipairs(df.global.world.raws.syndromes.all) do
if syndrome.syn_name == "Super Saiyan God" then return syn_id end
end
qerror("Super saiyan god syndrome not found.")
end
local function getCombatSkills(unit)
local totalSkill=0
for skill=99,104 do --fighting, wrestling, striking etc.
totalSkill=(dfhack.units.getNominalSkill(unit,skill)*100)+totalSkill
end
totalSkill=(dfhack.units.getNominalSkill(unit,df.job_skill.DODGING)*245)+totalSkill
totalSkill=(dfhack.units.getNominalSkill(unit,df.job_skill.SITUATIONAL_AWARENESS)*150)+totalSkill
return totalSkill
end
local function getPowerLevel(unit)
local strength = unit.body.physical_attrs.STRENGTH.value*1.5
local endurance = unit.body.physical_attrs.ENDURANCE.value*1.2
local toughness = unit.body.physical_attrs.TOUGHNESS.value*1.5
local spatialsense = unit.status.current_soul.mental_attrs.SPATIAL_SENSE.value
local kinestheticsense = unit.status.current_soul.mental_attrs.KINESTHETIC_SENSE.value*1.1
local willpower = unit.status.current_soul.mental_attrs.WILLPOWER.value/1.5
local agility = unit.body.physical_attrs.AGILITY.value*2
local bodysize = (unit.body.blood_max/75)^2
local powerlevel = bodysize+agility+strength+endurance+toughness+spatialsense+kinestheticsense+willpower
powerlevel=powerlevel+getCombatSkills(unit)
local superSaiyanLevel=getSuperSaiyanLevel(unit)
if superSaiyanLevel>0 then
powerlevel=powerlevel*50
if superSaiyanLevel>1 then
powerlevel=powerlevel*2
if superSaiyanLevel>2 then
powerlevel=powerlevel*4
end
end
end
return powerlevel
end
local function getSuperSaiyanCount()
local superSaiyanCount = 0
for _,unit in ipairs(df.global.world.units.active) do
if dfhack.units.isCitizen(unit) and getSuperSaiyanLevel(unit)>0 then
superSaiyanCount = superSaiyanCount + 1
end
end
return superSaiyanCount
end
local function unitWithHighestPowerLevel()
local highestUnit = nil
local highestPowerLevel = 0
for _,unit in ipairs(df.global.world.units.active) do
if dfhack.units.isCitizen(unit) and dfhack.units.isDwarf(unit) and getPowerLevel(unit) > highestPowerLevel then highestUnit = unit end
end
return highestUnit
end
local function combinedSaiyanPowerLevel()
local totalPowerLevel=0
for _,unit in ipairs(df.global.world.units.active) do
if dfhack.units.isCitizen(unit) then totalPowerLevel = totalPowerLevel + getPowerLevel(unit) end
end
return totalPowerLevel
end
local function assignSyndrome(target,syn_id) --taken straight from here, but edited so I can understand it better: https://gist.github.com/warmist/4061959/
if target==nil then
qerror("Not a valid target") --this probably won't happen :V
end
local newSyndrome=df.unit_syndrome:new()
local target_syndrome=df.syndrome.find(syn_id)
newSyndrome.type=target_syndrome.id
--newSyndrome.year=
--newSyndrome.year_time=
newSyndrome.ticks=1
newSyndrome.unk1=1
for k,v in ipairs(target_syndrome.ce) do
local sympt=df.unit_syndrome.T_symptoms:new()
sympt.ticks=1
sympt.flags=2
newSyndrome.symptoms:insert("#",sympt)
end
target.syndromes.active:insert("#",newSyndrome)
end
local function applySuperSaiyanGodSyndrome()
if df.global.gamemode==0 then
local superSaiyanCount = getSuperSaiyanCount()
if superSaiyanCount==0 then return nil end
local superSaiyanGod = unitWithHighestPowerLevel()
if superSaiyanGod and getPowerLevel(superSaiyanGod) > 1000000 and superSaiyanCount > 5 then assignSyndrome(superSaiyanGod,superSaiyanGodSyndrome()) end
elseif df.global.gamemode==1 then
assignSyndrome(df.global.world.units.active[0],superSaiyanGodSyndrome())
end
end
local function stopMegabeastAttacks()
local removedMegaBeastAttack = false
for eventid,event in ipairs(df.global.timed_events) do
if event.type == df.timed_event_type.Megabeast then
table.remove(df.global.timed_events,eventid)
removedMegaBeastAttack = true
end
end
return removedMegaBeastAttack
end
local function causeMegaBeastAttack()
df.global.timed_events:insert('#', { new = df.timed_event, type = df.timed_event_type.Megabeast, season = df.global.cur_season, season_ticks = df.global.cur_season_tick } )
end
local function checkForMegabeastAttack()
if combinedSaiyanPowerLevel() > 4000000 and stopMegabeastAttacks() then causeMegaBeastAttack() end
end
function monthlyCheck()
applySuperSaiyanGodSyndrome()
checkForMegabeastAttack()
dfhack.timeout(1,'months',monthlyCheck)
end
monthlyCheck()
local function getInorganic(item)
return dfhack.matinfo.decode(item).inorganic
end
local function tailClipSyndrome()
return df.global.world.raws.inorganics[dfhack.matinfo.find("DB_DFHACK_SYNDROME_HOLDER").index].material.syndrome[0].id --that's a doozy, hehe
end
local function giveName(unit,nameCopy)
for ii=1,3 do
local unitName = ii==1 and unit.name or ii==2 and unit.status.current_soul.name or df.historical_figure.find(unit.hist_figure_id).name
unitName.first_name = nameCopy.first_name
unitName.nickname = nameCopy.nickname
unitName.language = nameCopy.language
unitName.unknown = nameCopy.unknown
for i=1,7 do
unitName.words[i-1] = nameCopy.words[i]
unitName.parts_of_speech[i-1] = nameCopy.parts_of_speech[i]
end
end
end
local function fuseTwoNames(unit1,unit2)
local name1=unit1.name
local name2=unit2.name
local newName = {}
newName.first_name = string.sub(name1.first_name,1,math.floor(#name1.first_name/2)) .. string.sub(name2.first_name,-math.ceil(#name2.first_name/2)) --cuts each name in two and combines the first half of the first name and the second half of the second
newName.nickname = ""
newName.language = name1.language
newName.unknown = name1.unknown
newName.words = {}
newName.parts_of_speech = {}
for i = 1, 7 do
if i%2==1 then
newName.words[i] = name2.words[i-1]
newName.parts_of_speech[i] = name1.parts_of_speech[i-1]
else
newName.words[i] = name1.words[i-1]
newName.parts_of_speech[i] = name2.parts_of_speech[i-1]
end
end
dfhack.gui.showPopupAnnouncement(name1.first_name .. " has fused with " .. name2.first_name .. " to become " .. newName.first_name .. "!",COLOR_BLUE,true)
giveName(unit1,newName)
end
local function insertSkill(unit,skill)
unit.status.current_soul.skills:insert('#',
{
new = df.unit_skill,
id = skill.id,
rating = skill.rating,
experience = skill.experience,
unused_counter = skill.unused_counter,
rusty = skill.rusty,
rust_counter = skill.rust_counter,
demotion_counter = skill.demotion_counter,
unk_1c = skill.unk_1c
}
)
end
local function combineSoul(unit1,unit2)
local firstUnitSoul = unit1.status.current_soul
local secondUnitSoul= unit2.status.current_soul
for k,attribute in ipairs(firstUnitSoul.mental_attrs) do
attribute.value = attribute.value + secondUnitSoul.mental_attrs[k].value
attribute.max_value = attribute.max_value + secondUnitSoul.mental_attrs[k].max_value
if attribute.value < 0 or attribute.value > 2^31-1 then attribute.value = 2^30 end
if attribute.max_value < 0 or attribute.max_value > 2^31-1 then attribute.max_value = 2^31-1 end
end
for _,skill2 in ipairs(secondUnitSoul.skills) do
local skillFound = false
for _,skill1 in ipairs(firstUnitSoul.skills) do
if skill2.id == skill1.id then
skillFound = true
skill1.rating = skill1.rating + skill2.rating
end
end
if not skillFound then
insertSkill(unit1,skill2)
end
end
--preferences are too much trouble for their worth
for k,trait1 in ipairs(firstUnitSoul.traits) do
local trait2 = secondUnitSoul.traits[k]
trait1 = math.floor((trait1+trait2)/2)
end
--unk5 and unk6 are... unknown to me, so...
end
local function combineBody(unit1,unit2)
local firstBody = unit1.body
local firstAppearance = unit1.appearance
local secondBody = unit2.body
local secondAppearance = unit2.appearance
firstBody.blood_max = firstBody.blood_max + secondBody.blood_max
firstBody.blood_count = firstBody.blood_max
for k,attribute in ipairs(firstBody.physical_attrs) do
attribute.value = attribute.value + secondBody.physical_attrs[k].value
attribute.max_value = attribute.max_value * secondBody.physical_attrs[k].max_value
if attribute.value < 0 or attribute.value > 2^31-1 then attribute.value = 2^30 end
if attribute.max_value < 0 or attribute.max_value > 2^31-1 then attribute.max_value = 2^31-1 end
end
for k,tissue in ipairs(firstBody.physical_attr_tissues) do
tissue = tissue + secondBody.physical_attr_tissues[k]
end
for k,modifier in ipairs(firstAppearance.body_modifiers) do
if #secondAppearance.body_modifiers>k+1 then modifier = math.floor((modifier+secondAppearance.body_modifiers[k])/2) end
end
for k,modifier in ipairs(firstAppearance.bp_modifiers) do
if #secondAppearance.bp_modifiers>k+1 then modifier = math.floor((modifier+secondAppearance.bp_modifiers[k])/2) end
end
for k,length1 in ipairs(firstAppearance.tissue_length) do
local length2 = #secondAppearance.tissue_length>k+1 and secondAppearance.tissue_length[k] or nil
if length2 then length1 = math.floor((length1+length2)/2) end
end
end
local function combineCounters(unit1,unit2)
local trait1 = dfhack.units.getMiscTrait(unit1,15,true)
local trait2 = dfhack.units.getMiscTrait(unit2,15,true)
local totalValue = trait1.value+trait2.value
trait1.value=(totalValue>100) and 100 or totalValue
end
local function fuseUnits(unit1,unit2)
if unit1.race~=unit2.race then
return nil
end
fuseTwoNames(unit1,unit2)
combineSoul(unit1,unit2)
combineBody(unit1,unit2)
combineCounters(unit1,unit2)
unit2.flags1.dead=true
dfhack.timeout(1,'ticks',function()
unit2.pos.x=-30000
unit2.pos.y=-30000
unit2.pos.z=-30000
end)
end
events=require 'plugins.eventful'
dialog=require 'gui.dialogs'
script=require 'gui.script'
local function fusion(reaction,unit,input_items,input_reagents,output_items,call_native)
local tbl={}
for k,u in ipairs(df.global.world.units.active) do
local name=dfhack.TranslateName(dfhack.units.getVisibleName(u))
if name=="" then name="?" end
if (df.global.gamemode==1 and u.race==df.global.world.units.active[0].race) or (df.global.gamemode==0 and dfhack.units.isDwarf(u) and dfhack.units.isCitizen(u)) then table.insert(tbl,{name,nil,u}) end
end
table.sort(tbl,function(a,b) return getPowerLevel(a[3])>getPowerLevel(b[3]) end)
script.start(function()
local unitsToFuse={}
repeat
for i=1,2 do
local ok, name, C = script.showListPrompt("Unit Selection","Choose " ..(i==1 and "first" or "second").. " Saiyan to fuse (by power level)",COLOR_WHITE,tbl)
if ok then table.insert(unitsToFuse,C[3]) end
end
if unitsToFuse[1]==unitsToFuse[2] then unitsToFuse[1]=nil unitsToFuse[2]=nil unitsToFuse={} end
until unitsToFuse[1] and unitsToFuse[2] and unitsToFuse[1]~=unitsToFuse[2]
fuseUnits(unitsToFuse[1],unitsToFuse[2])
assignSyndrome(unitsToFuse[1],tailClipSyndrome())
end)
call_native.value=false
end
events.registerReaction("LUA_HOOK_FUSION_DB",fusion)
local function fixOverflow(a)
a=(a<0) and 2^30-1 or a
end
local function checkOverflows(unit)
for _,attribute in ipairs(unit.body.physical_attrs) do
fixOverflow(attribute.value)
end
for _,soul in ipairs(unit.status.souls) do --soul[0] is a pointer to the current soul
for _,attribute in ipairs(soul.mental_attrs) do
fixOverflow(attribute.value)
end
end
fixOverflow(unit.body.blood_max)
fixOverflow(unit.body.blood_count)
end
local function fixAllOverflows()
for _,unit in ipairs(df.global.world.units.active) do
checkOverflows(unit)
end
end
kamehamehaMat=dfhack.matinfo.find("KAMEHAMEHA_DB")
events.onProjItemCheckMovement.dragonball=function(projectile)
if dfhack.matinfo.decode(projectile.item)==kamehamehaMat then
dfhack.maps.spawnFlow(projectile.cur_pos,3,0,kamehamehaMat.index,400)
end
end
function add_site(size,civ,site_type,name)
local x=(df.global.world.map.region_x+1)%16;
local y=(df.global.world.map.region_y+1)%16;
local minx,miny,maxx,maxy
if(x<size) then
minx=0
maxx=2*size
elseif(x+size>16) then
maxx=16
minx=16-2*size
else
minx=x-size
maxx=x+size
end
if(y<size) then
miny=0
maxy=2*size
elseif(y+size>16) then
maxy=16
miny=16-2*size
else
miny=y-size
maxy=y+size
end
require("plugins.dfusion.adv_tools").addSite(nil,nil,maxx,minx,maxy,miny,civ,name,site_type)
end
function claimSite(reaction,unit,input_items,input_reagents,output_items,call_native)
dialog.showInputPrompt("Site name", "Select a name for a new site:", nil,nil, dfhack.curry(add_site,1,unit.civ_id,0))
call_native.value=false
end
events.registerReaction("LUA_HOOK_MAKE_SITE3x3",claimSite)
plug=require"plugins.dfusion.friendship"
plug.Friendship:install{"SAIYAN","SAIYAN","SAIBAMEN_DB","FRIEZA","MAJIN_BOO","ANDROID_DB","HUMAN","DWARF","ELF","NAMEK"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment