rjw-race-support-AsmodeusRex/generator/src/parts.rs

563 lines
19 KiB
Rust

use std::collections::HashMap;
#[derive(Clone, Copy, Debug)]
pub enum PartType {
Anus,
Breasts,
Penis,
Vagina,
}
#[derive(Clone, Debug)]
pub struct Part {
pub part_type: PartType,
pub name: String,
pub label: String,
pub label_noun: String,
pub description: String,
pub props: Vec<&'static str>,
}
impl Part {
fn standard(pre: &'static str, ty: PartType, species: &'static str, desc: &'static str, props: Vec<&'static str>) -> Option<Self> {
let mut name = species.to_owned() + match ty {
PartType::Anus => "Anus",
PartType::Breasts => return None,
PartType::Penis => "Penis",
PartType::Vagina => "Vagina",
};
if let Some(c) = name.get_mut(0..1) {
c.make_ascii_uppercase();
};
let label_type = match ty {
PartType::Anus => "anus",
PartType::Breasts => panic!(),
PartType::Penis => "penis",
PartType::Vagina => "vagina",
};
let label = format!("{species} {label_type}");
let label_noun = format!("{pre} {species} {label_type}");
Some(Self {
part_type: ty,
name: name,
label: label,
label_noun: label_noun,
description: desc.to_string(),
props: props
})
}
}
pub fn construct_racepart(part: &Part) -> String {
String::from(RACEPART_STRING).replace("{name}", &part.name)
}
pub fn construct_hediff(part: &Part, human: bool) -> String {
let mut s = String::from(HEDIFF_STRING);
let ty = match part.part_type {
PartType::Anus => "Anus",
PartType::Breasts => return "".to_string(),
PartType::Penis => "Penis",
PartType::Vagina => "Vagina",
};
let mut props = String::new();
for prop in &part.props {
props.push_str(&format!("\n\t\t\t\t\t<li>{prop}</li>"));
}
if human {
props.push_str(&format!("\n\t\t\t\t\t<li>Humanlike</li>"));
}
let replace = HashMap::from([
("{type}", ty),
("{name}", &part.name),
("{label}", &part.label),
("{label_noun}", &part.label_noun),
("{description}", &part.description),
("{props}", &props),
]);
for r in replace {
s = s.replace(r.0, r.1);
}
s
}
const HEDIFF_STRING: &'static str = "
<rjw.HediffDef_PartBase ParentName=\"NaturalPrivatePart{type}\">
<defName>{name}</defName>
<label>{label}</label>
<labelNoun>{label_noun}</labelNoun>
<description>{description}</description>
<descriptionHyperlinks>
<ThingDef>{name}</ThingDef>
</descriptionHyperlinks>
<spawnThingOnRemoved>{name}</spawnThingOnRemoved>
<modExtensions>
<li Class=\"rjw.PartProps\">
<props>{props}
</props>
</li>
</modExtensions>
</rjw.HediffDef_PartBase>";
const HEDIFF_STRING_EXT: &'static str = "
<rjw.HediffDef_PartBase ParentName=\"NaturalPrivatePart{type}\">
<defName>{name}</defName>
<label>{label}</label>
<labelNoun>{label_noun}</labelNoun>
<description>{description}</description>
<descriptionHyperlinks>
<ThingDef>{name}</ThingDef>
</descriptionHyperlinks>
<spawnThingOnRemoved>{name}</spawnThingOnRemoved>
{fields}<modExtensions>
<li Class=\"rjw.PartProps\">
<props>{props}
</props>
</li>
</modExtensions>
</rjw.HediffDef_PartBase>\n";
const HEDIFF_STRING_BREASTS: &'static str = "
<rjw.HediffDef_PartBase ParentName=\"{type}\">
<defName>{name}</defName>
<label>{label}</label>
<labelNoun>{label_noun}</labelNoun>
<description>{description}</description>
<descriptionHyperlinks>
<ThingDef>{name}</ThingDef>
</descriptionHyperlinks>
<spawnThingOnRemoved>{name}</spawnThingOnRemoved>
{fields}<modExtensions>
<li Class=\"rjw.PartProps\">
<props>{props}
</props>
</li>
</modExtensions>
</rjw.HediffDef_PartBase>\n";
const RACEPART_STRING: &'static str = "
<rjw.RacePartDef>
<defName>{name}</defName>
<hediffName>{name}</hediffName>
</rjw.RacePartDef>";
pub fn part_data_animals() -> Vec<Part> {
vec![
// Mammals
Part::standard("a", PartType::Penis, "bear",
"A small penis supported by a bone.",
vec!["Flared", "Small", "Rigid"]
).unwrap(),
Part::standard("a", PartType::Penis, "bovine",
"A rather long but thin penis with large testicles.",
vec!["Long", "Sheathed", "Thin"]
).unwrap(),
Part::standard("a", PartType::Vagina, "bovine",
"A rather thin and deep vagina, likely belonging to a large mammal.",
vec!["Tight", "Deep"]
).unwrap(),
Part::standard("a", PartType::Anus, "dog",
"A canine anus.",
vec![]
).unwrap(),
Part::standard("a", PartType::Penis, "dino",
"A large tapered penis that is slightly flattened at the top. It looks similar to a large tongue.",
vec!["Girthy", "Tapered", "Internal"]
).unwrap(),
Part::standard("an", PartType::Penis, "elephant",
"A large and flexible prehensile penis.",
vec!["Girthy", "Long", "Prehensile", "Sheathed"]
).unwrap(),
Part::standard("an", PartType::Vagina, "elephant",
"The deep vagina of a female elephant.",
vec!["Deep"]
).unwrap(),
Part::standard("an", PartType::Anus, "equine",
"An anus shaped like a doughnut.",
vec!["Loose"]
).unwrap(),
Part::standard("a", PartType::Anus, "feline",
"A feline anus.",
vec!["Tight"]
).unwrap(),
Part::standard("a", PartType::Penis, "monkey",
"A very thin, but otherwise humanoid-looking penis.",
vec!["Thin"]
).unwrap(),
Part::standard("a", PartType::Penis, "pig",
"A corkscrew shaped penis.",
vec!["Long", "Sheathed", "Thin"]
).unwrap(),
Part::standard("a", PartType::Vagina, "pig",
"The foldy vagina of a female pig.",
vec!["Tight"]
).unwrap(),
Part {
part_type: PartType::Vagina,
name: "MammalVagina".to_string(),
label: "mammal vagina".to_string(),
label_noun: "a mammalian vagina".to_string(),
description: "A generic vagina that probably belongs to some mammal.".to_string(),
props: vec![],
},
Part {
part_type: PartType::Anus,
name: "MammalAnus".to_string(),
label: "mammal anus".to_string(),
label_noun: "a mammalian anus".to_string(),
description: "A generic mammalian animal's anus.".to_string(),
props: vec![],
},
Part {
part_type: PartType::Anus,
name: "CervineAnus".to_string(),
label: "cervine anus".to_string(),
label_noun: "a deer anus".to_string(),
description: "A deer's anus.".to_string(),
props: vec![],
},
Part {
part_type: PartType::Vagina,
name: "HyenaVagina".to_string(),
label: "hyena pseudo-penis".to_string(),
label_noun: "a hyena pseudo-penis".to_string(),
description: "The clitoris of the female spotted hyena is enlarged into a pseudo-penis, through which the female urinates and reproduces. It can even get erect!".to_string(),
props: vec!["Barbed", "Deep"],
},
Part {
part_type: PartType::Penis,
name: "MarinePenis".to_string(),
label: "marine penis".to_string(),
label_noun: "a marine mammal penis".to_string(),
description: "A girthy, retractable penis that tapers to a point; it likely belongs to a seal, walrus, or hippo.".to_string(),
props: vec!["Girthy", "Internal", "Tapered"],
},
Part {
part_type: PartType::Vagina,
name: "MarineVagina".to_string(),
label: "marine vagina".to_string(),
label_noun: "a marine mammal vagina".to_string(),
description: "A slippery vagina.".to_string(),
props: vec!["Loose"],
},
// Non-Mammals
Part::standard("a", PartType::Penis, "cactoid",
"A rough plant-like penis, with thorns along the shaft.",
vec!["Barbed", "Ridged"]
).unwrap(),
Part::standard("a", PartType::Vagina, "cactoid",
"A rough plant-like vagina, with thorns lining the inner walls. The thorns grip male genitals during sex.",
vec!["Barbed", "Ridged"]
).unwrap(),
Part::standard("a", PartType::Anus, "cactoid",
"A rough plant-like anus. No thorns this time.",
vec!["Barbed", "Ridged"]
).unwrap(),
Part::standard("a", PartType::Penis, "turtle",
"A large penis with a huge flare at the tip.",
vec!["Flared", "Girthy", "Internal", "Long"]
).unwrap(),
Part {
part_type: PartType::Penis,
name: "Aedeagus".to_string(),
label: "aedeagus".to_string(),
label_noun: "an aedeagus".to_string(),
description: "The phallus of a male arthropod, for excreting a spermatophore to inseminate a female arthropod.".to_string(),
props: vec!["Rigid"],
},
Part {
part_type: PartType::Vagina,
name: "OviporeVagina".to_string(),
label: "ovipore".to_string(),
label_noun: "an ovipore".to_string(),
description: "A pore-like sexual organ of a female arthropod for receiving a spermatophore. Very loosely comparable to a vagina.".to_string(),
props: vec!["Rigid"],
},
Part {
part_type: PartType::Penis,
name: "AntherPenis".to_string(),
label: "anther".to_string(),
label_noun: "a flower's anther".to_string(),
description: "A flower's male reproductive organ. A long and thin filament, with a large pollen-producing head in the tip.".to_string(),
props: vec!["Long", "Thin"],
},
Part {
part_type: PartType::Vagina,
name: "PistilVagina".to_string(),
label: "pistil".to_string(),
label_noun: "a flower's pistil".to_string(),
description: "A flower's female reproductive organ. The sticky entrance is connected to the ovaries via a long tube-like structure.".to_string(),
props: vec![],
},
Part {
part_type: PartType::Penis,
name: "TentaclePenis".to_string(),
label: "tentacles".to_string(),
label_noun: "reproductive tentacles".to_string(),
description: "A mass of tentacle-like penises, capable of both restraining and pleasuring.".to_string(),
props: vec!["Long", "Multiple", "Prehensile"],
},
Part {
part_type: PartType::Penis,
name: "VinePenis".to_string(),
label: "vines".to_string(),
label_noun: "a mass of vines".to_string(),
description: "Genetically altered vines capable of reproduction.".to_string(),
props: vec!["Long", "Multiple", "Prehensile", "Thin"],
},
]
}
pub fn part_data_humans() -> Vec<Part> {
vec![
Part::standard("a", PartType::Penis, "necro",
"A disgusting, rotting penis that somehow still works.",
vec![]
).unwrap(),
Part::standard("a", PartType::Vagina, "necro",
"A disgusting, rotting vagina. Its insides are as cold as a grave.",
vec!["Loose"]
).unwrap(),
Part::standard("a", PartType::Anus, "necro",
"A disgusting, rotting anus. Its insides are as cold as a grave.",
vec!["Loose"]
).unwrap(),
Part::standard("an", PartType::Penis, "elf",
"A thinner and longer humanlike penis. Is that glitter?",
vec!["Long", "Thin"]
).unwrap(),
Part::standard("an", PartType::Vagina, "elf",
"A tighter humanlike vagina. Tastes like oranges.",
vec!["Tight"]
).unwrap(),
Part::standard("an", PartType::Anus, "elf",
"A tighter humanlike anus. Smells of flowers.",
vec!["Tight"]
).unwrap(),
Part::standard("a", PartType::Penis, "golem",
"A rough and jagged stone-like penis.",
vec!["Rigid", "Solid"]
).unwrap(),
Part::standard("an", PartType::Penis, "ghoul",
"A humanlike penis that glows slightly. It's very hot to the touch.",
vec!["Glowing"]
).unwrap(),
Part::standard("a", PartType::Vagina, "ghoul",
"A humanlike vagina that glows slightly. It is uncomfortably hot inside.",
vec!["Glowing"]
).unwrap(),
Part::standard("a", PartType::Anus, "ghoul",
"An anus that glows slightly. It is uncomfortably hot inside.",
vec!["Glowing"]
).unwrap(),
Part::standard("an", PartType::Penis, "orc",
"A girthy penis with a preputial ring, but otherwise similar to a humanoid penis.",
vec!["Girthy"]
).unwrap(),
Part::standard("an", PartType::Vagina, "orc",
"A loose humanlike vagina with very large lips.",
vec!["Loose"]
).unwrap(),
Part::standard("an", PartType::Anus, "orc",
"An anus that looks like a mix between an humanlike anus and an equine anus.",
vec!["Loose"]
).unwrap(),
Part {
part_type: PartType::Penis,
name: "TreePenis".to_string(),
label: "bark penis".to_string(),
label_noun: "a wooden penis".to_string(),
description: "A naturally grown wooden penis. The testicles are completely covered in hard, wooden bark, while the texture along the shaft is softer, leaving the tip uncovered.".to_string(),
props: vec!["Ridged", "Rigid"],
},
Part {
part_type: PartType::Vagina,
name: "TreeVagina".to_string(),
label: "bark vagina".to_string(),
label_noun: "a wooden vagina".to_string(),
description: "A naturally grown wooden vagina. While the outside looks like bark, the inside is soft.".to_string(),
props: vec!["Ridged", "Rigid"],
},
Part {
part_type: PartType::Anus,
name: "TreeAnus".to_string(),
label: "bark anus".to_string(),
label_noun: "a wooden anus".to_string(),
description: "A naturally grown wooden anus. While the outside looks like bark, the inside is soft.".to_string(),
props: vec!["Ridged", "Rigid"],
},
]
}
pub fn part_data_breasts() -> (Vec<Part>, String) {
let breasts = vec![
(Part {
part_type: PartType::Breasts,
name: "MammalBreasts".to_string(),
label: "mammal breasts".to_string(),
label_noun: "a pair of mammalian breasts".to_string(),
description: "A group of breasts/nipples that mammals use to suckle their young.".to_string(),
props: vec![],
}, "MammalBreastBase", None),
(Part {
part_type: PartType::Breasts,
name: "CatBreasts".to_string(),
label: "kitty titties".to_string(),
label_noun: "the kitty's titties".to_string(),
description: "It's the kitty's titties!".to_string(),
props: vec![],
}, "MammalBreastBase", None),
(Part {
part_type: PartType::Breasts,
name: "GhostBreasts".to_string(),
label: "immaterial breasts".to_string(),
label_noun: "a pair of immaterial breasts".to_string(),
description: "A translucent, almost intangible pair of breasts. Touching them sends chills down the spine.".to_string(),
props: vec!["Humanlike"],
}, "NaturalPrivatePartBreast", Some(
"<FluidType>Ecto</FluidType>\n\t\t"
)),
(Part {
part_type: PartType::Breasts,
name: "CactoidBreasts".to_string(),
label: "cactoid breasts".to_string(),
label_noun: "a pair of cactoid breasts".to_string(),
description: "A pair of rough plant-like breasts, with thorns all around them, and flower-like nipples.".to_string(),
props: vec![],
}, "NaturalPrivatePartBreast", None),
(Part {
part_type: PartType::Breasts,
name: "GhoulBreasts".to_string(),
label: "irradiated breasts".to_string(),
label_noun: "a pair of irradiated breasts".to_string(),
description: "A pair of humanlike breasts that glow slightly. They're very hot to the touch.".to_string(),
props: vec!["Humanlike"],
}, "NaturalPrivatePartBreast", None),
(Part {
part_type: PartType::Breasts,
name: "NecroBreasts".to_string(),
label: "decayed breasts".to_string(),
label_noun: "A pair of decayed breasts".to_string(),
description: "A disgusting, rotting pair of breasts.".to_string(),
props: vec!["Humanlike"],
}, "NaturalPrivatePartBreast", None),
(Part {
part_type: PartType::Breasts,
name: "OrcBreasts".to_string(),
label: "orc breasts".to_string(),
label_noun: "a pair of orc breasts".to_string(),
description: "A pair of humanlike breasts that sag greatly.".to_string(),
props: vec!["Humanlike"],
}, "NaturalPrivatePartBreast", None),
(Part {
part_type: PartType::Breasts,
name: "ScaleBreasts".to_string(),
label: "scaly breasts".to_string(),
label_noun: "a pair of scaly breasts".to_string(),
description: "A pair of scale-covered breasts, without nipples.".to_string(),
props: vec!["Humanlike"],
}, "NaturalPrivatePartBreast", None),
(Part {
part_type: PartType::Breasts,
name: "TreeBreasts".to_string(),
label: "bark breasts".to_string(),
label_noun: "a pair of wooden breasts".to_string(),
description: "A pair of naturally grown wooden breasts. Hard bark covers the entire outer portion, while leaving the nipples underneath exposed.".to_string(),
props: vec!["Humanlike", "Ridged", "Rigid"],
}, "NaturalPrivatePartBreast", None),
];
let mut hediffs = String::new();
for breast in &breasts {
let mut s = String::from(HEDIFF_STRING_BREASTS);
let mut props = String::new();
for prop in &breast.0.props {
props.push_str(&format!("\n\t\t\t\t\t<li>{prop}</li>"));
}
let fields = breast.2.unwrap_or("");
let replace = HashMap::from([
("{type}", breast.1),
("{name}", &breast.0.name),
("{label}", &breast.0.label),
("{label_noun}", &breast.0.label_noun),
("{description}", &breast.0.description),
("{fields}", &fields),
("{props}", &props),
]);
for r in replace {
s = s.replace(r.0, r.1);
}
hediffs.push_str(&s);
}
(breasts.into_iter().map(|x| x.0).collect(), hediffs)
}
pub fn part_data_other() -> (Vec<Part>, String) {
let parts = vec![
(Part {
part_type: PartType::Penis,
name: "GhostPenis".to_string(),
label: "immaterial penis".to_string(),
label_noun: "an immaterial penis".to_string(),
description: "A translucent, almost intangible penis. Touching it sends chills down the spine.".to_string(),
props: vec!["Humanlike"],
}, "<FluidType>Ecto</FluidType>\n\t\t".to_string() ),
(Part {
part_type: PartType::Vagina,
name: "GhostVagina".to_string(),
label: "immaterial vagina".to_string(),
label_noun: "an immaterial vagina".to_string(),
description: "A translucent, almost intangible vagina. Penetrating it sends chills down the spine.".to_string(),
props: vec!["Humanlike"],
}, "<FluidType>Ecto</FluidType>\n\t\t".to_string() ),
(Part {
part_type: PartType::Anus,
name: "GhostAnus".to_string(),
label: "immaterial anus".to_string(),
label_noun: "an immaterial anus".to_string(),
description: "A translucent, almost intangible anus. Penetrating it sends chills down the spine.".to_string(),
props: vec!["Humanlike"],
}, "<FluidType>Ecto</FluidType>\n\t\t".to_string() ),
(Part {
part_type: PartType::Vagina,
name: "DemonTentaclesF".to_string(),
label: "demon tentacle".to_string(),
label_noun: "a female demon tentacle".to_string(),
description: "A long and flexible tentacle, capable of laying eggs.".to_string(),
props: vec!["Long", "Prehensile"],
}, "<produceEggs>true</produceEggs>
<minEggTick>12000</minEggTick>
<maxEggTick>60000</maxEggTick>
<FluidType>GR_EldritchInsectJelly</FluidType>\n\t\t".to_string() ),
];
let mut hediffs = String::new();
for part in &parts {
let mut s = String::from(HEDIFF_STRING_EXT);
let ty = match part.0.part_type {
PartType::Anus => "Anus",
PartType::Breasts => panic!(),
PartType::Penis => "Penis",
PartType::Vagina => "Vagina",
};
let mut props = String::new();
for prop in &part.0.props {
props.push_str(&format!("\n\t\t\t\t\t<li>{prop}</li>"));
}
let replace = HashMap::from([
("{type}", ty),
("{name}", &part.0.name),
("{label}", &part.0.label),
("{label_noun}", &part.0.label_noun),
("{description}", &part.0.description),
("{fields}", &part.1),
("{props}", &props),
]);
for r in replace {
s = s.replace(r.0, r.1);
}
hediffs.push_str(&s);
}
(parts.into_iter().map(|x| x.0).collect(), hediffs)
}