feat(characters): add modular woodland traveler kit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
@tool
|
||||
class_name CharacterAppearanceProfile
|
||||
extends Resource
|
||||
## Authored, cosmetic building blocks. Never part of authoritative simulation saves.
|
||||
|
||||
const SPECIES: Array[StringName] = [&"cat", &"fox", &"rabbit", &"badger", &"otter"]
|
||||
const PART_SPECIES: Array[String] = ["Cat", "Fox", "Rabbit", "Badger", "Otter"]
|
||||
const OUTFITS: Array[String] = ["Vest", "Coat", "Tunic"]
|
||||
const EARS: Array[String] = ["", "Cat", "Fox", "Rabbit", "Lop", "Badger", "Otter"]
|
||||
const HATS: Array[String] = ["", "Beret", "Brim"]
|
||||
const BAGS: Array[String] = ["", "Satchel", "Travel"]
|
||||
|
||||
@export_enum("Cat", "Fox", "Rabbit", "Badger", "Otter") var species := 0
|
||||
@export_group("Proportions")
|
||||
@export_range(0.80, 1.15, 0.01) var height := 1.0
|
||||
@export_range(0.0, 1.0, 0.01) var body_fullness := 0.68
|
||||
@export_range(0.88, 1.12, 0.01) var head_size := 1.0
|
||||
@export_range(0.85, 1.15, 0.01) var leg_length := 1.0
|
||||
@export_range(0.65, 1.20, 0.01) var ear_length := 1.0
|
||||
@export_group("Building blocks")
|
||||
@export_enum("Vest", "Long coat", "Work tunic") var outfit := 0
|
||||
@export_enum("Relaxed", "Holding pack straps") var arm_pose := 1
|
||||
@export_enum("Species default", "Cat", "Fox", "Rabbit", "Lop", "Badger", "Otter") var ears := 0
|
||||
@export_enum("None", "Beret", "Brimmed hat") var hat := 0
|
||||
@export_enum("None", "Satchel", "Travel pack") var bag := 2
|
||||
@export var scarf := true
|
||||
@export var spectacles := false
|
||||
@export_group("Palette")
|
||||
@export var fur_color := Color("c78a4e")
|
||||
@export var muzzle_color := Color("eee4d1")
|
||||
@export var outfit_color := Color("496a9d")
|
||||
@export var linen_color := Color("efe6d4")
|
||||
@export var scarf_color := Color("7295bf")
|
||||
@export var trousers_color := Color("7995b6")
|
||||
@export var leather_color := Color("6f4937")
|
||||
|
||||
|
||||
static func for_identity(identity: int) -> CharacterAppearanceProfile:
|
||||
var result := CharacterAppearanceProfile.new()
|
||||
if identity == 0:
|
||||
return result
|
||||
# Integer arithmetic is stable across rebuilds and never consumes an RNG stream.
|
||||
var seed_value := posmod(identity, 100003)
|
||||
result.species = seed_value % SPECIES.size()
|
||||
result.height = 0.85 + float((seed_value * 17) % 29) / 100.0
|
||||
result.body_fullness = float((seed_value * 37) % 101) / 100.0
|
||||
result.head_size = 0.94 + float((seed_value * 7) % 15) / 100.0
|
||||
result.leg_length = 0.90 + float((seed_value * 11) % 22) / 100.0
|
||||
result.ear_length = 0.80 + float((seed_value * 13) % 36) / 100.0
|
||||
result.outfit = (seed_value / 3) % OUTFITS.size()
|
||||
result.arm_pose = 0
|
||||
result.bag = 1 if seed_value % 3 == 0 else 0
|
||||
result.hat = 1 if seed_value % 4 == 0 else 0
|
||||
result.scarf = seed_value % 3 != 1
|
||||
result.spectacles = seed_value % 7 == 0
|
||||
if result.species == 2 and seed_value % 2 == 0:
|
||||
result.ears = 4
|
||||
var furs := [
|
||||
Color("c78a4e"), Color("b77949"), Color("c4b7a4"), Color("c9c4b5"), Color("826c55")
|
||||
]
|
||||
var coats := [Color("496a9d"), Color("798362"), Color("986347"), Color("686b84")]
|
||||
result.fur_color = furs[result.species]
|
||||
result.outfit_color = coats[(seed_value / 5) % coats.size()]
|
||||
result.scarf_color = coats[(seed_value / 7 + 1) % coats.size()].lightened(0.2)
|
||||
return result
|
||||
|
||||
|
||||
func normalized_copy() -> CharacterAppearanceProfile:
|
||||
var result := duplicate() as CharacterAppearanceProfile
|
||||
result.species = clampi(species, 0, SPECIES.size() - 1)
|
||||
result.height = clampf(height, 0.80, 1.15)
|
||||
result.body_fullness = clampf(body_fullness, 0.0, 1.0)
|
||||
result.head_size = clampf(head_size, 0.88, 1.12)
|
||||
result.leg_length = clampf(leg_length, 0.85, 1.15)
|
||||
result.ear_length = clampf(ear_length, 0.65, 1.20)
|
||||
result.outfit = clampi(outfit, 0, OUTFITS.size() - 1)
|
||||
result.arm_pose = clampi(arm_pose, 0, 1)
|
||||
result.ears = clampi(ears, 0, EARS.size() - 1)
|
||||
result.hat = clampi(hat, 0, HATS.size() - 1)
|
||||
result.bag = clampi(bag, 0, BAGS.size() - 1)
|
||||
return result
|
||||
|
||||
|
||||
func ear_part() -> String:
|
||||
return PART_SPECIES[species] if ears == 0 else EARS[ears]
|
||||
Reference in New Issue
Block a user