#include "world/cast.h" #include /* Who they are: likes (firewood, trees, trash, fire), how willing, skills, a few words; tempo, thinking it over, breaks. */ #define SKILLS(wood, trees, trash, fire) \ { [ORDER_FIREWOOD] = wood, [ORDER_TREES] = trees, [ORDER_TRASH] = trash, [ORDER_FIRE] = fire } #define LOOK(sr, sg, sb, hr, hg, hb, tr, tg, tb, pr, pg, pb, fr, fg, fb, tall, hairdo, sleeves) \ { .skin = { sr, sg, sb }, .hair = { hr, hg, hb }, .shirt = { tr, tg, tb }, .pants = { pr, pg, pb }, .shoes = { fr, fg, fb }, \ .height = tall, .hair_style = hairdo, .long_sleeves = sleeves } static const CastMember CAST[] = { { .name = "You", .temperament = { .pride = 0.0f, .energy = 0.2f, .nerves = 0.1f }, .look = LOOK(0.93f, 0.74f, 0.60f, 0.30f, 0.19f, 0.12f, 0.86f, 0.42f, 0.32f, 0.24f, 0.30f, 0.48f, 0.22f, 0.16f, 0.13f, 1.78f, HAIR_SHORT, false), .character = { { 0 }, 1.0f, SKILLS(0.3f, 0.3f, 0.3f, 0.3f), NULL, 1.0f, 0.0f, BREAK_NONE, 0.0f, 0.0f }, .kg = 75, .age = 28, .hand = HAND_RIGHT, .garment = GARMENT_TROUSERS, .lighter = true, .filter_habit = true, .pocket_tray = true, .smoker = 0.3f, .wits = 0.6f, .height_fear = 0.2f, .worn = 0.15f, .fitness = 0.5f, .tolerance = 1.0f, .tobacco = POUCH_ROLLUPS, .papers = PAPERS_PACK, .filters = FILTERS_BAG, .role = "the web things with Volkram; helps or takes over wherever needed", .leads = PROJECT_WEB, .helps = PROJECT_NONE, .commitment = 1.0f }, { .name = "Volkram", .temperament = { .pride = 0.5f, .energy = 0.1f, .nerves = 0.0f }, .look = LOOK(0.90f, 0.70f, 0.56f, 0.42f, 0.30f, 0.18f, 0.36f, 0.46f, 0.36f, 0.30f, 0.27f, 0.24f, 0.25f, 0.18f, 0.12f, 1.86f, HAIR_LONG, true), .character = { SKILLS(0.8f, 0.3f, 0.0f, 0.6f), 0.7f, SKILLS(0.6f, 0.4f, 0.3f, 0.6f), "Volkram. Jana and I share a tent. Splitting wood clears my head.", 1.0f, 0.8f, BREAK_COFFEE, 90.0f, 30.0f }, .kg = 88, .age = 31, .hand = HAND_RIGHT, .garment = GARMENT_TROUSERS, .lighter = true, .filter_habit = true, .smoker = 0.6f, .wits = 0.7f, .height_fear = 0.15f, .worn = 0.2f, .fitness = 0.55f, .tolerance = 1.2f, .tobacco = 40, .papers = 20, .filters = 60, .keys = "Car keys", .role = "leads the festival organisation; the web things with you", .leads = PROJECT_ORGA, .helps = PROJECT_WEB, .commitment = 0.95f }, { .name = "Jana", .temperament = { .pride = 0.1f, .energy = 0.7f, .nerves = 0.3f }, .look = LOOK(0.96f, 0.80f, 0.68f, 0.70f, 0.36f, 0.20f, 0.92f, 0.78f, 0.36f, 0.42f, 0.30f, 0.46f, 0.85f, 0.82f, 0.74f, 1.66f, HAIR_LONG, false), .character = { SKILLS(0.0f, -0.5f, 0.6f, 0.9f), 0.8f, SKILLS(0.3f, 0.2f, 0.5f, 0.6f), "Jana! I'm here for the fire and the people. And I like it tidy.", 1.1f, 0.5f, BREAK_CHAT, 70.0f, 30.0f }, .kg = 60, .age = 29, .hand = HAND_LEFT, .garment = GARMENT_SKIRT, .female = true, .urinella = true, .filter_habit = true, .pocket_tray = true, .smoker = 0.2f, .wits = 0.65f, .height_fear = 0.5f, .worn = 0.1f, .fitness = 0.7f, .tolerance = 0.8f, .tobacco = 10, .papers = 5, .role = "one of the crew (her task not settled yet)", .leads = PROJECT_NONE, .helps = PROJECT_DECORATION, .commitment = 0.75f }, { .name = "Toni", .temperament = { .pride = -0.3f, .energy = 0.4f, .nerves = 0.6f }, .look = LOOK(0.72f, 0.52f, 0.38f, 0.12f, 0.10f, 0.10f, 0.30f, 0.62f, 0.60f, 0.55f, 0.48f, 0.36f, 0.32f, 0.22f, 0.16f, 1.74f, HAIR_SHORT, false), .character = { SKILLS(0.4f, 0.6f, -0.4f, 0.3f), 0.5f, SKILLS(0.4f, 0.4f, 0.2f, 0.3f), "Toni. First time out here. Show me how and I'll do it.", 1.2f, 0.3f, BREAK_WALK, 80.0f, 25.0f }, .kg = 70, .age = 26, .hand = HAND_RIGHT, .garment = GARMENT_SHORTS, .lighter = true, .filter_habit = true, .smoker = 0.7f, .wits = 0.5f, .height_fear = 0.1f, .worn = 0.35f, .fitness = 0.8f, .tolerance = 0.9f, .tobacco = 25, .papers = 0, .filters = 15, .role = "artist organisation with Rouven; builds along; mows the Kartoffelacker with the scythe", .leads = PROJECT_MOWING, .helps = PROJECT_ARTISTS, .commitment = 0.8f }, { .name = "Kurti", .temperament = { .pride = 0.3f, .energy = -0.6f, .nerves = 0.0f }, .look = { .skin = { 0.90f, 0.72f, 0.62f }, .hair = { 0.82f, 0.82f, 0.80f }, .shirt = { 0.55f, 0.50f, 0.42f }, .pants = { 0.33f, 0.36f, 0.30f }, .shoes = { 0.20f, 0.16f, 0.12f }, .height = 1.70f, .hair_style = HAIR_SHORT, .long_sleeves = true, .belly = 1.0f, .keeps_shirt = true }, .character = { SKILLS(0.6f, 0.7f, 0.2f, 0.8f), 0.4f, SKILLS(0.8f, 0.9f, 0.4f, 0.8f), "Kurti. This is my house - you're welcome. I've felled more trees than you've seen.", 0.7f, 2.2f, BREAK_SIT, 45.0f, 50.0f }, .kg = 72, .age = 74, .hand = HAND_RIGHT, .garment = GARMENT_TROUSERS, .lighter = true, .lives_here = true, .smoker = 0.8f, .wits = 0.75f, .height_fear = 0.7f, .worn = 0.4f, .fitness = 0.12f, .tolerance = 1.4f, .tobacco = 60, .papers = 30, .keys = "House keys", .role = "the farm is his: the host", .leads = PROJECT_NONE, .helps = PROJECT_NONE, .commitment = 0.6f }, { .name = "Martin", .temperament = { .pride = 0.8f, .energy = 0.3f, .nerves = 0.1f }, .look = LOOK(0.88f, 0.66f, 0.50f, 0.30f, 0.22f, 0.16f, 0.20f, 0.24f, 0.40f, 0.24f, 0.26f, 0.30f, 0.18f, 0.14f, 0.12f, 1.84f, HAIR_SHORT, false), .character = { SKILLS(0.4f, 0.9f, -0.6f, 0.3f), 0.5f, SKILLS(0.7f, 0.8f, 0.2f, 0.4f), "Martin. Kurti's eldest. Give me a chainsaw, not a broom.", 1.2f, 0.2f, BREAK_NONE, 0.0f, 0.0f }, .kg = 92, .age = 30, .hand = HAND_RIGHT, .garment = GARMENT_TROUSERS, .lighter = true, .lives_here = true, .smoker = 0.4f, .wits = 0.55f, .height_fear = 0.05f, .worn = 0.2f, .fitness = 0.6f, .tolerance = 1.3f, .cigarettes = 12, .role = "Kurti's eldest: one of the hosts", .leads = PROJECT_NONE, .helps = PROJECT_NONE, .commitment = 0.5f }, { .name = "Jonas", .temperament = { .pride = -0.1f, .energy = 0.6f, .nerves = 0.2f }, .look = LOOK(0.90f, 0.70f, 0.55f, 0.36f, 0.26f, 0.18f, 0.80f, 0.20f, 0.18f, 0.50f, 0.46f, 0.38f, 0.60f, 0.24f, 0.20f, 1.80f, HAIR_SHORT, false), .character = { SKILLS(0.6f, 0.4f, 0.3f, 0.5f), 0.85f, SKILLS(0.4f, 0.4f, 0.4f, 0.4f), "Jonas. The younger one. Dad says I talk too much.", 1.15f, 0.4f, BREAK_CHAT, 80.0f, 30.0f }, .kg = 76, .age = 25, .hand = HAND_LEFT, .garment = GARMENT_SHORTS, .lives_here = true, .smoker = 0.0f, .wits = 0.45f, .height_fear = 0.2f, .worn = 0.1f, .fitness = 0.85f, .tolerance = 1.0f, .role = "Kurti's younger son: one of the hosts", .leads = PROJECT_NONE, .helps = PROJECT_NONE, .commitment = 0.6f }, /* ----- the crew, turning up over the first days ----- */ { .name = "Kilian", .temperament = { .pride = 0.3f, .energy = 0.5f, .nerves = 0.2f }, .look = LOOK(0.92f, 0.73f, 0.60f, 0.55f, 0.40f, 0.22f, 0.48f, 0.24f, 0.58f, 0.18f, 0.18f, 0.20f, 0.30f, 0.26f, 0.22f, 1.83f, HAIR_LONG, false), .character = { SKILLS(0.6f, 0.4f, 0.0f, 0.5f), 0.6f, SKILLS(0.6f, 0.5f, 0.3f, 0.5f), "Kilian. The Obstwiese is going to be a psy floor like you've never seen. Give me wood and a week.", 1.1f, 0.6f, BREAK_COFFEE, 100.0f, 25.0f }, .kg = 78, .age = 33, .hand = HAND_RIGHT, .garment = GARMENT_TROUSERS, .lighter = true, .smoker = 0.5f, .wits = 0.7f, .height_fear = 0.1f, .worn = 0.25f, .fitness = 0.65f, .tolerance = 1.0f, .tobacco = 50, .papers = 30, .filters = 40, .role = "builds the Obstwiese stage (psytrance)", .leads = PROJECT_OBSTWIESE, .helps = PROJECT_HOFBUEHNE, .commitment = 0.9f, .arrives = 2.0f }, { .name = "Julia", .temperament = { .pride = 0.2f, .energy = 0.8f, .nerves = 0.1f }, .look = LOOK(0.94f, 0.78f, 0.66f, 0.20f, 0.14f, 0.10f, 0.36f, 0.52f, 0.30f, 0.30f, 0.30f, 0.34f, 0.40f, 0.30f, 0.20f, 1.70f, HAIR_LONG, false), .character = { SKILLS(0.6f, 0.4f, 0.4f, 0.4f), 0.95f, SKILLS(0.7f, 0.6f, 0.7f, 0.6f), "Julia. Tell me what needs doing - building's what I like best.", 1.35f, 0.2f, BREAK_NONE, 0.0f, 0.0f }, .kg = 62, .age = 27, .hand = HAND_RIGHT, .garment = GARMENT_TROUSERS, .female = true, .filter_habit = true, .smoker = 0.0f, .wits = 0.8f, .height_fear = 0.05f, .worn = 0.1f, .fitness = 0.75f, .tolerance = 0.9f, .role = "quick at every job, very good at building: wherever she's needed", .leads = PROJECT_NONE, .helps = PROJECT_HOFBUEHNE, .commitment = 0.9f, .arrives = 2.0f }, { .name = "Stella", .temperament = { .pride = 0.1f, .energy = 0.5f, .nerves = 0.3f }, .look = LOOK(0.95f, 0.78f, 0.66f, 0.85f, 0.62f, 0.30f, 0.90f, 0.50f, 0.66f, 0.30f, 0.50f, 0.52f, 0.70f, 0.60f, 0.40f, 1.68f, HAIR_LONG, false), .character = { SKILLS(-0.3f, -0.4f, 0.4f, 0.5f), 0.7f, SKILLS(0.2f, 0.1f, 0.5f, 0.4f), "Stella. Doro and I do the art - and the snails, they're protected, you know.", 1.0f, 0.7f, BREAK_CHAT, 70.0f, 35.0f }, .kg = 58, .age = 30, .hand = HAND_RIGHT, .garment = GARMENT_DRESS, .female = true, .urinella = true, .filter_habit = true, .pocket_tray = true, .smoker = 0.3f, .wits = 0.7f, .height_fear = 0.4f, .worn = 0.1f, .fitness = 0.6f, .tolerance = 0.8f, .tobacco = 20, .papers = 15, .filters = 30, .role = "art and decoration with Doro; the snail rescue", .leads = PROJECT_DECORATION, .helps = PROJECT_SNAILS, .commitment = 0.85f, .arrives = 5.0f }, { .name = "Doro", .temperament = { .pride = 0.0f, .energy = 0.3f, .nerves = 0.2f }, .look = LOOK(0.88f, 0.66f, 0.52f, 0.25f, 0.16f, 0.12f, 0.30f, 0.30f, 0.56f, 0.58f, 0.40f, 0.30f, 0.28f, 0.22f, 0.18f, 1.72f, HAIR_SHORT, true), .character = { SKILLS(-0.2f, -0.3f, 0.5f, 0.4f), 0.75f, SKILLS(0.2f, 0.1f, 0.5f, 0.4f), "Doro. Paint, fabric, lights in the trees - and nobody steps on a snail.", 0.95f, 0.8f, BREAK_SIT, 80.0f, 35.0f }, .kg = 64, .age = 32, .hand = HAND_LEFT, .garment = GARMENT_TROUSERS, .female = true, .lighter = true, .smoker = 0.0f, .wits = 0.75f, .height_fear = 0.3f, .worn = 0.15f, .fitness = 0.55f, .tolerance = 0.9f, .role = "leads the snail rescue; art and decoration with Stella", .leads = PROJECT_SNAILS, .helps = PROJECT_DECORATION, .commitment = 0.85f, .arrives = 5.0f }, { .name = "Kerry", .temperament = { .pride = 0.4f, .energy = 0.0f, .nerves = 0.0f }, .look = LOOK(0.86f, 0.64f, 0.48f, 0.50f, 0.42f, 0.36f, 0.34f, 0.30f, 0.26f, 0.26f, 0.30f, 0.22f, 0.26f, 0.20f, 0.14f, 1.79f, HAIR_LONG, true), .character = { SKILLS(0.6f, 0.9f, -0.5f, 0.6f), 0.5f, SKILLS(0.8f, 0.9f, 0.2f, 0.6f), "Kerry. Give me a log and a chainsaw and I'll find what's in it.", 0.9f, 1.2f, BREAK_COFFEE, 120.0f, 40.0f }, .kg = 84, .age = 41, .hand = HAND_RIGHT, .garment = GARMENT_TROUSERS, .lighter = true, .smoker = 0.6f, .wits = 0.7f, .height_fear = 0.1f, .worn = 0.2f, .fitness = 0.6f, .tolerance = 1.3f, .cigarettes = 8, .role = "wood art with the chainsaw (needs logs and the chainsaw)", .leads = PROJECT_WOOD_ART, .helps = PROJECT_DECORATION, .commitment = 0.7f, .arrives = 20.0f }, { .name = "Rouven", .temperament = { .pride = 0.3f, .energy = 0.4f, .nerves = 0.3f }, .look = LOOK(0.93f, 0.75f, 0.62f, 0.24f, 0.18f, 0.12f, 0.20f, 0.20f, 0.22f, 0.20f, 0.22f, 0.28f, 0.82f, 0.82f, 0.80f, 1.81f, HAIR_SHORT, false), .character = { SKILLS(0.0f, -0.3f, 0.2f, 0.6f), 0.6f, SKILLS(0.3f, 0.2f, 0.4f, 0.5f), "Rouven. Toni and I do the artists - who plays when, and that they're happy.", 1.0f, 0.6f, BREAK_CHAT, 70.0f, 30.0f }, .kg = 74, .age = 29, .hand = HAND_RIGHT, .garment = GARMENT_TROUSERS, .lighter = true, .filter_habit = true, .smoker = 0.4f, .wits = 0.75f, .height_fear = 0.3f, .worn = 0.15f, .fitness = 0.5f, .tolerance = 1.0f, .tobacco = 30, .papers = 20, .filters = 50, .role = "artist organisation with Toni", .leads = PROJECT_ARTISTS, .helps = PROJECT_HOFBUEHNE, .commitment = 0.8f, .arrives = 26.0f }, { .name = "Pascal", .temperament = { .pride = 0.2f, .energy = 0.2f, .nerves = 0.1f }, .look = LOOK(0.90f, 0.70f, 0.56f, 0.18f, 0.14f, 0.12f, 0.22f, 0.22f, 0.24f, 0.26f, 0.28f, 0.34f, 0.20f, 0.18f, 0.16f, 1.77f, HAIR_SHORT, true), .character = { SKILLS(0.3f, 0.2f, 0.0f, 0.3f), 0.7f, SKILLS(0.5f, 0.3f, 0.3f, 0.4f), "Pascal. Light is what I do - and the main stage gets a proper floor.", 1.05f, 0.9f, BREAK_COFFEE, 110.0f, 30.0f }, .kg = 80, .age = 35, .hand = HAND_RIGHT, .garment = GARMENT_TROUSERS, .lighter = true, .smoker = 0.2f, .wits = 0.8f, .height_fear = 0.05f, .worn = 0.15f, .fitness = 0.55f, .tolerance = 1.1f, .cigarettes = 6, .role = "the light, and a proper floor for the main stage", .leads = PROJECT_LIGHT, .helps = PROJECT_HOFBUEHNE, .commitment = 0.85f, .arrives = 26.0f }, { .name = "Enrico", .temperament = { .pride = 0.4f, .energy = 0.3f, .nerves = -0.2f }, .look = LOOK(0.84f, 0.62f, 0.46f, 0.15f, 0.12f, 0.10f, 0.70f, 0.42f, 0.16f, 0.26f, 0.30f, 0.22f, 0.30f, 0.22f, 0.14f, 1.83f, HAIR_LONG, false), .character = { SKILLS(0.6f, 0.9f, -0.2f, 0.4f), 0.6f, SKILLS(0.7f, 0.95f, 0.3f, 0.5f), "Enrico, Go-Darmstadt - the geo-dome lot. Trees? I've felled bigger ones than that.", 1.05f, 1.2f, BREAK_SIT, 100.0f, 30.0f }, .kg = 86, .age = 38, .hand = HAND_RIGHT, .garment = GARMENT_TROUSERS, .lighter = true, .far_away = true, .smoker = 0.5f, .wits = 0.7f, .height_fear = 0.0f, .worn = 0.3f, .fitness = 0.7f, .tolerance = 1.3f, .cigarettes = 14, .role = "Go-Darmstadt (the geo-dome); fells the big old tree away from the phone line", .leads = PROJECT_BIG_TREE, .helps = PROJECT_KARTOFFELACKER, .commitment = 0.85f, .arrives = 21.0f }, }; #define CAST_COUNT ((int)(sizeof(CAST) / sizeof(CAST[0]))) int Cast_count(void) { return CAST_COUNT; } const CastMember *Cast_get(int id) { return id >= 0 && id < CAST_COUNT ? &CAST[id] : NULL; } Object *Cast_create(int id, Vec3 at) { const CastMember *c = Cast_get(id); if (!c) return NULL; Object *obj = Object_create(id == 0 ? OBJ_PLAYER : OBJ_HUMAN, PALETTE_MODERN, at, vec3(0.5f, 1.75f, 0.25f), c->kg); if (!obj) return NULL; obj->cast_id = id; obj->temperament = c->temperament; obj->tolerance = c->tolerance; obj->fitness = c->fitness; FigureLook worn = Figure_wardrobe(id); /* (the jacket, its hood and a hat from the wardrobe; the rest their own) */ obj->look = c->look; obj->look.jacket = worn.jacket; obj->look.hoodie = worn.hoodie; obj->look.hat = worn.hat; obj->look.hat_color = worn.hat_color; obj->look.garment = c->garment; Object_setPerson(obj, c->name, c->hand); obj->ai.character = c->character; obj->female = c->female; obj->urinella = c->urinella; obj->urinellas = c->urinella ? POCKET_URINELLAS - 1 : 0; obj->urinella_tried = c->urinella ? 1 : 0; /* (who has them knows she likes them) */ obj->lighter = c->lighter; obj->lighter_uses = c->lighter ? LIGHTER_USES * (1 + id % 3) / 3 : 0; /* (some nearly empty) */ obj->smoker = c->smoker; obj->wits = c->wits; obj->height_fear = c->height_fear; obj->worn = c->worn; obj->cigarettes = c->cigarettes; obj->tobacco = c->tobacco; obj->papers = c->papers; obj->filters = c->filters; obj->filter_habit = c->filter_habit; obj->pocket_tray = c->pocket_tray; obj->lives_here = c->lives_here; obj->keys = c->keys; obj->work_trousers = id == 0; /* (you: work trousers, plenty of pockets) */ obj->craving = 0.3f + 0.15f * (float)(id % 3); obj->commitment = c->commitment; obj->like = c->lives_here ? 0.45f : 0.5f + 0.25f * c->commitment; /* (you: the crew are friends; the hosts friendly) */ obj->love = 0.05f + 0.2f * (float)((id * 2654435761u) >> 24 & 255u) / 255.0f; /* (a little, here and there) */ obj->leads = (int)c->leads; obj->helps = (int)c->helps; for (int k = 0; k < ORDER_COUNT; k++) obj->skill[k] = c->character.skill[k]; obj->tempo = c->character.tempo; Object_setHeight(obj, obj->look.height); /* (the body box their own size) */ float years = clampf(1.0f - (float)(c->age - 45) / 60.0f, 0.5f, 1.0f); /* (old legs) */ obj->top_speed *= years; obj->jump_speed *= years; obj->pace = years * (1.0f + 0.12f * obj->temperament.energy); /* (Kurti: old and calm - he takes his time) */ return obj; } const char *Cast_projectName(Project p) { static const char *const NAMES[PROJECT_COUNT] = { [PROJECT_NONE] = "-", [PROJECT_ORGA] = "organisation", [PROJECT_WEB] = "web and tickets", [PROJECT_ARTISTS] = "artists", [PROJECT_DECORATION] = "decoration", [PROJECT_LIGHT] = "light", [PROJECT_HOFBUEHNE] = "Hofbuehne (bands)", [PROJECT_OBSTWIESE] = "Obstwiese (psytrance)", [PROJECT_KARTOFFELACKER] = "Kartoffelacker (world music)", [PROJECT_HIDDEN] = "hidden floor (techno)", [PROJECT_MOWING] = "mowing (scythe)", [PROJECT_SNAILS] = "snail rescue", [PROJECT_WOOD_ART] = "wood art (chainsaw)", [PROJECT_BIG_TREE] = "big old tree", }; return p >= 0 && p < PROJECT_COUNT && NAMES[p] ? NAMES[p] : "?"; } Object *Cast_leadOf(Object *const *objects, int count, Project p) { if (p == PROJECT_NONE) return NULL; for (int i = 0; i < count; i++) if (objects[i]->is_character && objects[i]->cast_id >= 0 && objects[i]->leads == (int)p) return objects[i]; return NULL; }