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.

Werebeast/script

From Dwarf Fortress Wiki
Jump to navigation Jump to search
werebeast_origin_interactions={}

-- this takes options, but remember that these should be pure functions,
-- meaning that they have no side-effects. Don't put anything into options
-- in these functions! Only read from it. If you want to add to options
-- based on these functions, put it into a subordinate table to
-- the return table, it'll be incorporated in the generated temp function
-- (the default does this, so it's a fine example)
werebeast_origin_interactions.default=function(tok,name,options)
    -- just in case you want your werebeast to never generate like this
    if options.no_default_werebeast_curse then return {weight=0,interaction={}} end
    local lines={}
    -- ACTUAL CHANGE FROM 50.13 AND EARLIER: PREVIOUSLY, THESE WOULD BE "DEITY_CURSE_WEREBEAST_1" ETC
    -- WITH THIS THEY'RE "DEITY_CURSE_WEREBEAST_dragonfly" etc. (incl. the lowercase)
    -- THIS IS FINE BECAUSE WE ACTUALLY FILTER OUT RCPs NOW, WHICH IS ANOTHER CHANGE FROM V50
    local interaction_token="DEITY_CURSE_WEREBEAST_"..name.."_"..tostring(random_object_parameters.werebeast_count+1)
    lines[#lines+1]="[INTERACTION:"..interaction_token.."]"
    add_generated_info(lines)
    lines[#lines+1]="[I_SOURCE:DEITY]"
    lines[#lines+1]="[IS_USAGE_HINT:MAJOR_CURSE]"
    lines[#lines+1]="[IS_HIST_STRING_1: cursed ]"
    lines[#lines+1]="[IS_HIST_STRING_2: to assume the form of a "..name.."-like monster every full moon"
    lines[#lines+1]="[IS_TRIGGER_STRING_SECOND:have]"
    lines[#lines+1]="[IS_TRIGGER_STRING_THIRD:has]"
    lines[#lines+1]="[IS_TRIGGER_STRING:been cursed to assume the form of a "..name.."-like monster every fool moon!"
    lines[#lines+1]="[I_TARGET:A:CREATURE]"
    lines[#lines+1]="[IT_LOCATION:CONTEXT_CREATURE]"
    lines[#lines+1]="[IT_REQUIRES:CAN_LEARN]"
    lines[#lines+1]="[IT_REQUIRES:HAS_BLOOD]"
    lines[#lines+1]="[IT_FORBIDDEN:NOT_LIVING]"
    lines[#lines+1]="[IT_FORBIDDEN:SUPERNATURAL]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:WERECURSE]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:VAMPCURSE]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:DISTURBANCE_CURSE]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:RAISED_UNDEAD]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:RAISED_GHOST]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:GHOUL]"
lines[#lines+1]="[I_EFFECT:ADD_SYNDROME]"
    lines[#lines+1]="[IE_TARGET:A]"
    lines[#lines+1]="[IE_IMMEDIATE]"
    lines[#lines+1]="[IE_ARENA_NAME:Werebeast]"
    lines[#lines+1]="[SYNDROME]"
        lines[#lines+1]="[SYN_CLASS:WERECURSE]"
        lines[#lines+1]="[SYN_CONCENTRATION_ADDED:1000:0]"--just in case
        lines[#lines+1]="[CE_BODY_TRANSFORMATION:START:0:ABRUPT]"
        lines[#lines+1]="[CE:CREATURE:"..tok..":DEFAULT]"
        -- moon phase variety? not for default, surely
        -- (consider future cosmology stuff, too; should world push moon phase info into a lua table?)
        lines[#lines+1]="[CE:PERIODIC:MOON_PHASE:27:0]"
        lines[#lines+1]="[CE_ADD_TAG:NO_AGING:START:0:ABRUPT]"
    lines[#lines+1]="[INTERACTION:"..interaction_token.."_BITE]"
    add_generated_info(lines)
    lines[#lines+1]="[I_SOURCE:ATTACK]"
    lines[#lines+1]="[IS_HIST_STRING_1: bit ]"
    lines[#lines+1]="[IS_HIST_STRING_2: passing on the "..name.." monster curse"
    lines[#lines+1]="[I_TARGET:A:CREATURE]"
    lines[#lines+1]="[IT_LOCATION:CONTEXT_CREATURE]"
    lines[#lines+1]="[IT_REQUIRES:CAN_LEARN]"
    lines[#lines+1]="[IT_REQUIRES:HAS_BLOOD]"
    lines[#lines+1]="[IT_FORBIDDEN:NOT_LIVING]"
    lines[#lines+1]="[IT_FORBIDDEN:SUPERNATURAL]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:WERECURSE]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:VAMPCURSE]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:DISTURBANCE_CURSE]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:RAISED_UNDEAD]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:RAISED_GHOST]"
    lines[#lines+1]="[IT_CANNOT_HAVE_SYNDROME_CLASS:GHOUL]"
lines[#lines+1]="[I_EFFECT:ADD_SYNDROME]"
    lines[#lines+1]="[IE_TARGET:A]"
    lines[#lines+1]="[IE_IMMEDIATE]"
    lines[#lines+1]="[SYNDROME]"
        lines[#lines+1]="[SYN_CLASS:WERECURSE]"
        lines[#lines+1]="[SYN_CONCENTRATION_ADDED:1000:0]"--just in case
        lines[#lines+1]="[CE_BODY_TRANSFORMATION:START:16800:ABRUPT]" -- an easy-werebeasts mod could remove the delay... or would that make it harder? fascinating stuff
        lines[#lines+1]="[CE:CREATURE:"..tok..":DEFAULT]"
        lines[#lines+1]="[CE:PERIODIC:MOON_PHASE:27:0]"
        lines[#lines+1]="[CE_ADD_TAG:NO_AGING:START:0:ABRUPT]"
    return {raws=lines,weight=1,options={bite_interaction=interaction_token.."_BITE"}}
end

creatures.night_creature.werebeast.default=function(tok)
    local lines={}
    local options={
        spheres={
            CHAOS=true,
            ANIMALS=true,
            NIGHT=true,
            MOON=true
        },
        always_glowing_eyes=true,
        use_werebeast_pcg=true,
        animal_coloring_allowed=true,
        no_tweak=true,
        material_weakness=true,
        humanoidable_only=true,
        beast_only=true,
        prioritize_bite=true,
        token=tok
    }
    options.night_creature_agile_pref=true
    night_creature_universals(lines,options)
    lines[#lines+1]="[NIGHT_CREATURE_HUNTER]"
    lines[#lines+1]="[CAN_LEARN]"
    lines[#lines+1]="[CAN_SPEAK]"
    lines[#lines+1]="[NO_GENDER]"
    lines[#lines+1]="[BONECARN]"
    lines[#lines+1]="[CRAZED]"
    if options.night_creature_strength_pref then
        lines[#lines+1]="[PHYS_ATT_RANGE:STRENGTH:1000:1250:1500:2000:2250:2500:3000]"
        lines[#lines+1]="[PHYS_ATT_RANGE:AGILITY:450:550:700:750:800:850:900]"
        lines[#lines+1]="[PHYS_ATT_RANGE:TOUGHNESS:850:900:950:1000:1050:1100:1150]"
        lines[#lines+1]="[PHYS_ATT_RANGE:ENDURANCE:850:900:950:1000:1050:1100:1150]"
        options.special_walk_speed=1000
    elseif options.night_creature_agile_pref then
        lines[#lines+1]="[PHYS_ATT_RANGE:STRENGTH:450:550:700:750:800:850:900]"
        lines[#lines+1]="[PHYS_ATT_RANGE:AGILITY:1000:1250:1500:2000:2250:2500:3000]"
        lines[#lines+1]="[PHYS_ATT_RANGE:TOUGHNESS:850:900:950:1000:1050:1100:1150]"
        lines[#lines+1]="[PHYS_ATT_RANGE:ENDURANCE:850:900:950:1000:1050:1100:1150]"
        options.special_walk_speed=800;
    elseif options.night_creature_strength_agile_pref then
        lines[#lines+1]="[PHYS_ATT_RANGE:STRENGTH:1000:1150:1250:1500:2000:2250:2500]"
        lines[#lines+1]="[PHYS_ATT_RANGE:AGILITY:1000:1150:1250:1500:2000:2250:2500]"
        lines[#lines+1]="[PHYS_ATT_RANGE:TOUGHNESS:850:900:950:1000:1050:1100:1150]"
        lines[#lines+1]="[PHYS_ATT_RANGE:ENDURANCE:850:900:950:1000:1050:1100:1150]"
        options.special_walk_speed=850;
    end
    lines[#lines+1]="[PHYS_ATT_RANGE:RECUPERATION:450:1050:1150:1250:1350:1550:2250]"
    lines[#lines+1]="[PHYS_ATT_RANGE:DISEASE_RESISTANCE:700:1300:1400:1500:1600:1800:2500]"
    lines[#lines+1]="[MENT_ATT_RANGE:ANALYTICAL_ABILITY:1250:1500:1750:2000:2500:3000:5000]"
    lines[#lines+1]="[MENT_ATT_RANGE:FOCUS:1250:1500:1750:2000:2500:3000:5000]"
    lines[#lines+1]="[MENT_ATT_RANGE:WILLPOWER:1250:1500:1750:2000:2500:3000:5000]"
    lines[#lines+1]="[MENT_ATT_RANGE:PATIENCE:0:333:666:1000:2333:3666:5000]"
    lines[#lines+1]="[MENT_ATT_RANGE:MEMORY:1250:1500:1750:2000:2500:3000:5000]"
    lines[#lines+1]="[MENT_ATT_RANGE:LINGUISTIC_ABILITY:450:1050:1150:1250:1350:1550:2250]"
    lines[#lines+1]="[MENT_ATT_RANGE:MUSICALITY:0:333:666:1000:2333:3666:5000]"
    lines[#lines+1]="[MENT_ATT_RANGE:SOCIAL_AWARENESS:700:1300:1400:1500:1600:1800:2500]"
    --[[
MENTAL_ATTRIBUTE_CREATIVITY,
MENTAL_ATTRIBUTE_INTUITION,
MENTAL_ATTRIBUTE_SPATIAL_SENSE,
MENTAL_ATTRIBUTE_KINESTHETIC_SENSE,
MENTAL_ATTRIBUTE_EMPATHY,
    ]]
    --lines[#lines+1]="[PERSONALITY:ANXIETY_PROPENSITY:0:0:0]"
    --lines[#lines+1]="[PERSONALITY:DEPRESSION_PROPENSITY:0:0:0]"
    lines[#lines+1]="[PERSONALITY:BASHFUL:0:0:0]"
    lines[#lines+1]="[PERSONALITY:STRESS_VULNERABILITY:0:0:0]"
    lines[#lines+1]="[PERSONALITY:FRIENDLINESS:0:0:0]"
    --lines[#lines+1]="[PERSONALITY:ASSERTIVENESS:100:100:100]"
    lines[#lines+1]="[PERSONALITY:DISDAIN_ADVICE:100:100:100]"
    lines[#lines+1]="[PERSONALITY:CHEER_PROPENSITY:0:0:0]"
    lines[#lines+1]="[PERSONALITY:GRATITUDE:0:0:0]"
    lines[#lines+1]="[PERSONALITY:TRUST:0:0:0]"
    lines[#lines+1]="[PERSONALITY:ALTRUISM:0:0:0]"
    --lines[#lines+1]="[PERSONALITY:SWAYED_BY_EMOTIONS:0:0:0]"
    lines[#lines+1]="[PERSONALITY:CRUELTY:100:100:100]"
    --lines[#lines+1]="[PERSONALITY:PRIDE:100:100:100]"

    add_regular_tokens(lines,options)
    populate_sphere_info(lines,options)
    lines[#lines+1]="[NATURAL_SKILL:WRESTLING:6]"
    lines[#lines+1]="[NATURAL_SKILL:BITE:6]"
    lines[#lines+1]="[NATURAL_SKILL:GRASP_STRIKE:6]"
    lines[#lines+1]="[NATURAL_SKILL:STANCE_STRIKE:6]"
    lines[#lines+1]="[NATURAL_SKILL:MELEE_COMBAT:6]"
    lines[#lines+1]="[NATURAL_SKILL:DODGING:6]"
    lines[#lines+1]="[NATURAL_SKILL:SITUATIONAL_AWARENESS:6]"
    lines[#lines+1]="[NATURAL_SKILL:SNEAK:20]"

    lines[#lines+1]="[DIFFICULTY:3]"
    lines[#lines+1]="[LAIR:SIMPLE_BURROW:50]"
    local ropar=random_object_parameters
    ropar.werebeast_blacklist=ropar.werebeast_blacklist or {}
    ropar.werebeast_count=ropar.werebeast_count or 0
    local rcp=get_random_creature_profile(options,ropar.werebeast_blacklist)
    if rcp.type=="GENERAL_BLOB" then
        ropar.werebeast_count=ropar.werebeast_count+1
        ropar.werebeast_blacklist={}
        rcp=get_random_creature_profile(options)
    end
    ropar.werebeast_blacklist[rcp.type]=true
    -- This sort of process should be fully generalized
    -- to all creatures you want to have bespoke associated interactions
    -- for example, you can have a blessing that allows a sort of
    -- uncrazed transformation into some sort of bespoke
    -- generated thing--at least, hopefully it's robust enough for that
    local choice=generate_from_list(werebeast_origin_interactions,tok,rcp.name_string,options)
    map_merge(options,choice.options)
    local werebeast_choice_raws=choice.interaction or choice.raws
    raws.register_interactions(werebeast_choice_raws)
    add_body_size(lines,math.max(rcp.min_size,80000+trandom(11)*1000),options)
    lines[#lines+1]="[CREATURE_TILE:165]" --Ñ
    options.forced_color={
        f=6,
        b=0,
        br=1
    }
    options.custom_desc_func=function(options)
        return "it is crazed for blood and flesh"
    end
    build_procgen_creature(rcp,lines,options)
    lines[#lines+1]="[GO_TO_START]"
    local name_str="were"..rcp.name_string..":were"..rcp.name_string.."s:were"..rcp.name_string.."]"
    lines[#lines+1]="[NAME:"..name_str
    lines[#lines+1]="[CASTE_NAME:"..name_str
    return {raws=lines,weight=1}
end