v50 Steam/Premium information for editors
  • v50 information can now be added to pages in the main namespace. v0.47 information can still be found in the DF2014 namespace. See here for more details on the new versioning policy.
  • Use this page to report any issues related to the migration.
This notice may be cached—the current version can be found here.

Angel/script

From Dwarf Fortress Wiki
< Angel
Revision as of 09:55, 30 June 2026 by Ziusudra (talk | contribs) (from 53.15 creatures.lua)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
sphere_flavor={
    AGRICULTURE={add="it looks constantly to the sky for rain"},
    ANIMALS={add="it growls, buzzes, clicks and generally makes a varied racket"},
    ART={add="it is decorated with intricate patterns"},
    BALANCE={add="it is perfectly symmetric"},
    BEAUTY={add="it is strikingly beautiful"},
    BIRTH={add="it is covered with a filmy sac"},
    BLIGHT={add="nearby vegetation seem to shrink away from it"},
    BOUNDARIES={add="the pieces of its body are carefully separated by markings"},
    CAVERNS={add="its moans seem to echo no matter where it resides"},
    CHAOS={add="it spins wildly, lurching and howling"},
    CHARITY={add="it seems very pleasant"},
    CHILDREN={add="it never misses an opportunity to jump in puddles"},
    COASTS={add="it appears to be covered with rocky crags"},
    CONSOLATION={add="it radiates a sad kindness"},
    COURAGE={add="it makes those around it feel brave"},
    CRAFTS={add="it appears constructed"},
    CREATION={add="small objects seem to pop into existence around it"},
    DANCE={add="it whirls, skips and jumps whenever it moves"},
    DARKNESS={add="it is difficult to see clearly even in bright light"},
    DAWN={add="it always turns to welcome the rise of the sun"},
    DAY={add="it hums pleasantly when the sun is high in the sky"},
    DEATH={add="it has a rattling exhale"},
    DEFORMITY={add="its body is bent and misshapen"},
    DEPRAVITY={add="it slavers uncontrollably"},
    DISCIPLINE={add="it moves with great focus"},
    DISEASE={add="it bears malodorous pustules",odor="death"},
    DREAMS={add="the details of its form are easily forgotten without deliberate concentration"},
    DUSK={add="it never looks toward the sun"},
    DUTY={add="it is utterly still when not taking deliberate action"},
    EARTH={add="it looks very solid and stocky"},
    FAMILY={add="it appears to be closely related to every other of its kind"},
    FAME={add="fanfare follows it wherever it goes"},
    FATE={add="it never appears to be perturbed or surprised by any happening"},
    FERTILITY={add="it appears to be very healthy"},
    FESTIVALS={add="it skips and twirls as it moves"},
    FIRE={add="a sheen around it always seems to rise upward"},
    FISH={add="it only looks comfortable when it is in the water"},
    FISHING={add="it always moves carefully around water"},
    FOOD={add="it has the delicious smell of freshly-baked goods",odor="freshly-baked goods"},
    FORGIVENESS={add="it is impossible to hold a grudge near it"},
    FORTRESSES={add="it is very sturdy-looking"},
    FREEDOM={add="it eagerly moves from place to place"},
    GAMBLING={add="it changes between two colors intermittently"},
    GAMES={add="it giggles at random"},
    GENEROSITY={add="it makes those around it want to give up their possessions"},
    HAPPINESS={add="it seems to smile constantly"},
    HEALING={add="it is surrounded by a gentle atmosphere"},
    HOSPITALITY={add="it radiates an aura of welcoming"},
    HUNTING={add="it inspects the ground intently as it moves"},
    INSPIRATION={add="flashes of energy pulse across its surface intermittently"},
    JEALOUSY={add="it appears to be a very bitter creature"},
    JEWELS={add="its whole body appears to be faceted in a symmetric fashion"},
    JUSTICE={add="it seems eager to pronounce judgment on others"},
    LABOR={add="it appears very deliberate in its actions"},
    LAKES={add="it moves ponderously"},
    LAWS={add="it has a very stark look about it"},
    LIES={add="it seems unerringly honest if one does not concentrate"},
    LIGHT={add="it returns surrounding light with a new vibrance and intensity"},
    LIGHTNING={add="it crackles with energy"},
    LONGEVITY={add="it always seems to be looking far into the distance"},
    LOVE={add="it stares longingly at those nearby"},
    LOYALTY={add="it never abandons its companions"},
    LUCK={add="it changes direction suddenly at times"},
    LUST={add="it has an unnerving stare"},
    MARRIAGE={add="it heckles those it meets that are not married"},
    MERCY={add="it always seems like it is on the verge of crying"},
    METALS={add="it appears to have sharp shimmering edges on many parts of its body"},
    MINERALS={add="it has an angular appearance"},
    MISERY={add="it has a distinctly depressing moan"},
    MIST={add="it is difficult to see clearly"},
    MOON={add="it changes color with the phases of the moon"},
    MOUNTAINS={add="it is very solidly built"},
    MUCK={add="there is a foul reek about it"},
    MURDER={add="it cannot abide anything that lives"},
    MUSIC={add="it sounds clear tones as its body moves in time"},
    NATURE={add="it seems most at ease when it is outdoors"},
    NIGHT={add="it eerily reflects the light of the stars and moon"},
    NIGHTMARES={add="it reminds those that look upon it of their most unpleasant memories"},
    OATHS={add="it cannot look directly at somebody that has broken an oath"},
    OCEANS={add="it always raises a part of its body toward the moon"},
    ORDER={add="it moves very stiffly"},
    PAINTING={add="its surface is always enlivened with a refreshing play of color"},
    PEACE={add="it has an incredibly calm demeanor"},
    PERSUASION={add="it rocks back and forth whenever somebody changes their mind in its presence"},
    PLANTS={add="it always seems to point toward the sun when it is in the sky"},
    POETRY={add="it recites verses in a strange language on occasion"},
    PREGNANCY={add="it appears to be expecting"},
    RAIN={add="it leaves water wherever it goes"},
    RAINBOWS={add="it is strikingly colored"},
    REBIRTH={add="it alternates from instant to instant between sluggishness and extreme vibrancy"},
    REVELRY={add="it moves with a bouncing rhythm"},
    REVENGE={add="it has a fixed and unblinking gaze when interacting"},
    RIVERS={add="its outer surface seems to flow about its body"},
    RULERSHIP={add="it is hard to disobey"},
    RUMORS={add="it always nods eagerly when somebody is speaking"},
    SACRIFICE={add="it inspires those around it to acts of great sacrifice"},
    SALT={add="it makes nearby water undrinkable"},
    SCHOLARSHIP={add="it always seems to be deep in thought"},
    SEASONS={add="its form is ever-changing"},
    SILENCE={add="it makes absolutely no sound"},
    SKY={add="it has a slowly shifting pattern on its surface"},
    SONG={add="it sings beautiful songs endlessly"},
    SPEECH={add="it pays attention carefully to anybody that is speaking"},
    STARS={add="it appears to sparkle after night falls"},
    STORMS={add="its movement is the sound of wind and rain"},
    STRENGTH={add="it looks solidly built"},
    SUICIDE={add="it mutters to itself about death"},
    SUN={add="it is difficult to look at directly"},
    THEFT={add="it always seems to have its attention on the most valuable object in the area"},
    THRALLDOM={add="its movements sound like the rattling of chains"},
    THUNDER={add="it is incredibly noisy"},
    TORTURE={add="it appears to be covered with sharp hooks and barbs"},
    TRADE={add="it seems most content when a fair wind is blowing"},
    TRAVELERS={add="it never stops moving completely"},
    TREACHERY={add="it is unsettling to be around"},
    TREES={add="it is top-heavy"},
    TRICKERY={add="it has a tendency to laugh quietly to itself every so often"},
    TRUTH={add="it tenses up throughout its entire body whenever somebody tells a falsehood in its presence"},
    TWILIGHT={add="it chitters briefly before sunrise and just after nightfall"},
    VALOR={add="it always tries to embolden any fighting in its presence with exhortations of bravery, even its foes"},
    VICTORY={add="it looks very proud of itself"},
    VOLCANOS={add="it seems to glow brightly from within"},
    WAR={add="it bellows and cheers without pause"},
    WATER={add="it seems to flow as it moves"},
    WEALTH={add="it always seems to be counting something"},
    WEATHER={add="it changes appearance based on the clouds and precipitation above"},
    WIND={add="it is surrounded by an everpresent rush of wind"},
    WISDOM={add="it acts with unwavering calm"},
    WRITING={add="it is covered with divine writing"},
    YOUTH={add="it appears spry and vigorous"},
}

function angel_description(lines,options)
    local ropar=random_object_parameters
    local end_str=" It was created by "
    local add_desc=function(str) end_str=end_str..str end
    local hf=ropar.source_hf
    if hf then
        add_desc("the ")
        add_desc(ropar.source_hf_race_adj.." ")
        if hf.gender==1 then add_desc("goddess")
        elseif hf.gender==0 then add_desc("god")
        else add_desc("deity") end
        add_desc(" ")
        add_desc(hf.name.translated)
    else
        add_desc("an unknown deity")
    end
    local sch=0
    for k,v in pairs(options.spheres) do
        if v then sch = sch+1 end
    end
    if sch>0 then
        add_desc(" and is of a part with ")
        for k,v in pairs(options.spheres) do
            add_desc(world.spheres[k].definite_name)
            sch=sch-1
            if sch>=2 then add_desc(", ")
            elseif sch == 1 then add_desc(" and ")
            end
        end
    end
    add_desc(".")
    return end_str
end

angel_names_humanoid_warrior={
    {"Angel","Angels","angelic"},
    {"Soldier","Soldiers","soldier"},
    {"Warrior","Warriors","warrior"},
    {"Champion","Champions","champion"},
    {"Fighter","Fighters","fighter"},
    {"Guardian","Guardians","guardian"},
    {"Spirit","Spirits","spirit"},
    {"Messenger","Messengers","messenger"},
    {"Slayer","Slayers","slayer"},
    {"Enforcer","Enforcers","enforcer"},
}

angel_names_great_beast={
    {"Beast","Beasts","beast"},
    {"Behemoth","Behemoths","behemoth"},
    {"Harbinger","Harbingers","harbinger"},
    {"Monster","Monsters","monster"},
    {"Destroyer","Destroyers","destroyer"},
    {"Doom","Dooms","doom"},
    {"Bane","Banes","bane"},
    {"Catastrophe","Catastrophes","catastrophe"},
    {"Ruination","Ruinations","ruination"},
    {"Judgment","Judgments","judgment"},
}

angel_names_humanoid_generic={
    {"Servant","Servants","servant"},
    {"Assistant","Assistants","assistant"},
    {"Attendant","Attendants","attendant"},
    {"Minion","Minions","minion"},
    {"Helper","Helpers","helper"},
    {"Worker","Workers","worker"},
    {"Hand","Hands","hand"},
    {"Being","Beings","being"},
    {"Puppet","Puppets","puppet"},
    {"Pawn","Pawns","pawn"},
    {"Retainer","Retainers","retainer"},
}

function angel_end_tokens(lines,options,names_tbl)
    lines[#lines+1]="[GO_TO_START]"
    local hf = random_object_parameters.source_hf
    local cand={}
    if hf.name.translated_epithet_compound then 
        cand[#cand+1]={
            hf.name.translated_epithet_compound,
            hf.name.native_epithet_compound,
            false}
    end
    if hf.name.translated_epithet_the then
        cand[#cand+1]={
            hf.name.translated_epithet_the,
            hf.name.native_epithet_the,
            false}
    end
    if hf.name.translated_epithet_the_adj1 then
        cand[#cand+1]={
            hf.name.translated_epithet_the_adj1,
            hf.name.native_epithet_the_adj1,
            false}
    end
    if string.len(hf.name.firstname) then
        cand[#cand+1]={hf.name.firstname,hf.name.firstname,true}
    end
    local god_name = pick_random(cand)
    local add_name,proper_name="",false
    if god_name then
        add_name=god_name[trandom(2)+1]
        proper_name=god_name[3]
    end
    local using_god_name=false
    local name_flags={}
    local have_adjective=false
    cand={}
    for k,v in pairs(options.spheres) do
        if v then cand[#cand+1]=k end
    end
    if #cand>0 and (string.len(add_name)==0 or one_in(2)) then
        proper_name=false
        if one_in(2) then
            have_adjective=true
            add_name=get_random_sphere_adjective(pick_random(cand))
        else
            local ret=get_random_sphere_noun(pick_random(cand))
            name_flags=ret.flags
            add_name=ret.str
        end
    else using_god_name=true
    end
    local name,names,name_adj=table.unpack(pick_random(names_tbl))
    local ntype
    if using_god_name and proper_name then ntype=trandom(2)+1
    elseif using_god_name then ntype=2
    elseif have_adjective or #name_flags==0 then ntype=0
    else 
        local cand={}
        if name_flags.PRE then cand[#cand+1]=0 end
        if name_flags.PREPOS then cand[#cand+1]=1 end
        if name_flags.OF then cand[#cand+1]=2 end
        ntype=pick_random(cand) or 0
    end
    local ntypes={
        function()
            return add_name.." "..name..":"..add_name.." "..names..":"..add_name.." "..name_adj
        end,
        function()
            return add_name.."'s "..name..":"..add_name.."'s "..names..":"..add_name.."'s "..name_adj
        end,
        function()
            return name.." of "..add_name..":"..names.." of "..add_name..":"..name_adj
        end,
    }
    local str=ntypes[ntype+1]()
    lines[#lines+1]="[NAME:"..str.."]"
    lines[#lines+1]="[CASTE_NAME:"..str.."]"
end

creatures.angel.humanoid_warrior.default=function(tok)
    local lines={}
    local options={
        can_learn=true,
        do_sphere_rcm=true,
        pick_sphere_rcm=true,
        force_ichor=true,
        sickness_name="divine sickness",
        forced_color={
            f=3,
            b=0,
            br=1
        },
        token=tok,
    }
    lines[#lines+1]="[DIFFICULTY:6]"
    lines[#lines+1]="[CAN_LEARN]"
    if one_in(2) then lines[#lines+1]="[CAN_SPEAK]" end
    add_regular_tokens(lines,options)
    options.spheres=options.spheres or {}
    local hf=random_object_parameters.source_hf
    if hf then
        if hf.profile and hf.profile.mpp then
            map_merge(options.spheres,hf.profile.mpp.sphere)
        end
    end
    local skill_amount = (options.spheres.WAR or options.spheres.VALOR or options.spheres.FORTRESSES) and "10" or "6"
    for k,v in ipairs({
    "WRESTLING","BITE","GRASP_STRIKE","STANCE_STRIKE",
    "MELEE_COMBAT","RANGED_COMBAT","DODGING","SITUATIONAL_AWARENESS",
    "AXE","SWORD","DAGGER","PIKE",
    "MACE","HAMMER","WHIP","SPEAR",}) do
        lines[#lines+1]="[NATURAL_SKILL:"..v..":"..skill_amount.."]"
    end
    populate_sphere_info(lines,options)
    local rcm
    if one_in(4) then
        options.humanoidable_only=true
        rcp=get_random_creature_profile(options)
    else
        rcp={
            type="GENERAL_HUMANOID",
            name_string="humanoid",
            tile='H',
            body_base="HUMANOID",
            min_size=1,
        }
        if options.sphere_rcm then
            rcp.c_class="UNIFORM"
        else
            --FOR SKIN/ORGANS AND NO HAIR/FEATHERS AT FIRST
            rcp.c_class="AMPHIBIAN"
            rcp.cannot_have_shell=true
        end
    end
    add_body_size(lines,math.max(rcp.min_size,50000+trandom(4)*10000+trandom(11)*1000),options)
    lines[#lines+1]="[CREATURE_TILE:"..((options.body_size<=60000) and "132]" or "142]") -- ä or Ä
    options.custom_desc_func=function(options)
        local add_tbl=sphere_flavor[pick_random_conditional_pairs(sphere_flavor,function(sphere,_,options) 
            return options.spheres[sphere] 
        end,options)]
        if not add_tbl then add_tbl={add="it is a divine being"} end
        if add_tbl.odor then
            options.always_odor=true
            options.forced_odor_string=add_tbl.odor
            options.forced_odor_level=100
        end
        return add_tbl.add
    end
    options.end_phrase=angel_description(lines,options)
    build_procgen_creature(rcp,lines,options)
    angel_end_tokens(lines,options,angel_names_humanoid_warrior)
    return {raws=lines,weight=1}
end

creatures.angel.humanoid_generic.default=function(tok)
    local lines={}
    local options={
        do_sphere_rcm=true,
        pick_sphere_rcm=true,
        force_ichor=true,
        sickness_name="divine sickness",
        forced_color={
            f=6,
            b=0,
            br=0
        },
        token=tok,
    }
    lines[#lines+1]="[LARGE_PREDATOR]"
    lines[#lines+1]="[DIFFICULTY:2]"
    lines[#lines+1]="[NATURAL_SKILL:WRESTLING:4]"
    lines[#lines+1]="[NATURAL_SKILL:BITE:4]"
    lines[#lines+1]="[NATURAL_SKILL:GRASP_STRIKE:4]"
    lines[#lines+1]="[NATURAL_SKILL:STANCE_STRIKE:4]"
    lines[#lines+1]="[NATURAL_SKILL:MELEE_COMBAT:4]"
    lines[#lines+1]="[NATURAL_SKILL:RANGED_COMBAT:4]"
    lines[#lines+1]="[NATURAL_SKILL:DODGING:4]"
    lines[#lines+1]="[NATURAL_SKILL:SITUATIONAL_AWARENESS:4]"
    add_regular_tokens(lines,options)
    options.spheres=options.spheres or {}
    local hf=random_object_parameters.source_hf
    if hf then
        if hf.profile and hf.profile.mpp then
            map_merge(options.spheres,hf.profile.mpp.sphere)
        end
    end
    populate_sphere_info(lines,options)
    local rcm
    if one_in(4) then
        options.humanoidable_only=true
        rcp=get_random_creature_profile(options)
    else
        rcp={
            type="GENERAL_HUMANOID",
            name_string="humanoid",
            tile='H',
            body_base="HUMANOID",
            min_size=1,
        }
        if options.sphere_rcm then
            rcp.c_class="UNIFORM"
        else
            --FOR SKIN/ORGANS AND NO HAIR/FEATHERS AT FIRST
            rcp.c_class="AMPHIBIAN"
            rcp.cannot_have_shell=true
        end
    end
    add_body_size(lines,math.max(rcp.min_size,50000+trandom(4)*10000+trandom(11)*1000),options)
    lines[#lines+1]="[CREATURE_TILE:"..((options.body_size<=60000) and "132]" or "142]") -- ä or Ä
    options.custom_desc_func=function(options)
        local add_tbl=sphere_flavor[pick_random_conditional_pairs(sphere_flavor,function(sphere,_,options) 
            return options.spheres[sphere] 
        end,options)]
        if not add_tbl then add_tbl={add="it is a divine being"} end
        if add_tbl.odor then
            options.always_odor=true
            options.forced_odor_string=add_tbl.odor
            options.forced_odor_level=100
        end
        return add_tbl.add
    end
    options.end_phrase=angel_description(lines,options)
    build_procgen_creature(rcp,lines,options)
    angel_end_tokens(lines,options,angel_names_humanoid_generic)
    return {raws=lines,weight=1}
end

creatures.angel.great_beast.default=function(tok)
    local lines={}
    local l=get_debug_logger()
    local options={
        can_learn=true,
        do_sphere_rcm=true,
        pick_sphere_rcm=true,
        force_ichor=true,
        beast_only=true,
        sickness_name="divine sickness",
        forced_color={
            f=4,
            b=0,
            br=1
        },
        token=tok,
    }
    lines[#lines+1]="[LARGE_PREDATOR]"
    lines[#lines+1]="[DIFFICULTY:10]"
    lines[#lines+1]="[NATURAL_SKILL:WRESTLING:14]"
    lines[#lines+1]="[NATURAL_SKILL:BITE:14]"
    lines[#lines+1]="[NATURAL_SKILL:GRASP_STRIKE:14]"
    lines[#lines+1]="[NATURAL_SKILL:STANCE_STRIKE:14]"
    lines[#lines+1]="[NATURAL_SKILL:MELEE_COMBAT:14]"
    lines[#lines+1]="[NATURAL_SKILL:RANGED_COMBAT:14]"
    lines[#lines+1]="[NATURAL_SKILL:DODGING:14]"
    lines[#lines+1]="[NATURAL_SKILL:SITUATIONAL_AWARENESS:14]"
    add_regular_tokens(lines,options)
    options.spheres=options.spheres or {}
    local hf=random_object_parameters.source_hf
    if hf then
        if hf.profile and hf.profile.mpp then
            map_merge(options.spheres,hf.profile.mpp.sphere)
        end
    end
    local skill_amount = (options.spheres.WAR or options.spheres.VALOR or options.spheres.FORTRESSES) and "10" or "6"
    for k,v in ipairs({
    "WRESTLING","BITE","GRASP_STRIKE","STANCE_STRIKE",
    "MELEE_COMBAT","RANGED_COMBAT","DODGING","SITUATIONAL_AWARENESS",
    "AXE","SWORD","DAGGER","PIKE",
    "MACE","HAMMER","WHIP","SPEAR"}) do
        lines[#lines+1]="[NATURAL_SKILL:"..v..":"..skill_amount.."]"
    end
    populate_sphere_info(lines,options)
    local rcm
    rcp=get_random_creature_profile(options)
    add_body_size(lines,math.max(rcp.min_size,10000000),options)
    lines[#lines+1]="[CREATURE_TILE:"..((options.body_size<=60000) and "132]" or "142]") -- ä or Ä
    options.custom_desc_func=function(options)
        local add_tbl=sphere_flavor[pick_random_conditional_pairs(sphere_flavor,function(sphere,_,options) 
            return options.spheres[sphere] 
        end,options)]
        if not add_tbl then add_tbl={add="it is a divine being"} end
        if add_tbl.odor then
            options.always_odor=true
            options.forced_odor_string=add_tbl.odor
            options.forced_odor_level=100
        end
        return add_tbl.add
    end
    options.end_phrase=angel_description(lines,options)
    build_procgen_creature(rcp,lines,options)
    angel_end_tokens(lines,options,angel_names_great_beast)
    return {raws=lines,weight=1}
end