Entropie git · main
Entropie festival game; first steps
C 88.5% Markdown 9.1% GLSL 2.3%git clone https://git.christianimmanuel.de/games/Entropie.gitwget https://git.christianimmanuel.de/games/Entropie/archive/Entropie.tar.gzentropie/src/world/object.h raw
#ifndef WORLD_OBJECT_H
#define WORLD_OBJECT_H
/*
* World object: mesh, transform, colliders and physics state.
*
* position is the base point (bottom center). The mesh origin sits at
* position + pivot and the object rotates around it. Colliders are defined
* in the same local space as the mesh, so they always match what you see.
*/
#include <stdbool.h>
#include <stddef.h>
#include "people/ai.h"
#include "people/body.h"
#include "people/hands.h"
#include "world/tools.h"
#include "math/linalg.h"
#include "render/figure.h"
#include "render/mesh.h"
#include "render/shapes.h"
/* Food over a fire: seconds (held right over the flames; on the grate half as fast) */
#define FOOD_DONE 6.0f /* done */
#define FOOD_DARK 11.0f /* getting too dark: take it off */
#define FOOD_BURNT 16.0f /* charcoal */
typedef enum {
OBJ_BOX, /* dynamic box, size = bounding box */
OBJ_BOX_STATIC, /* static box, size = bounding box */
OBJ_CYLINDER, /* dynamic cylinder, size = bounding box (box collider) */
OBJ_CYLINDER_STATIC, /* static cylinder, size = bounding box (box collider) */
OBJ_HUMAN, /* 2D painted person, size = collider box */
OBJ_PLAYER, /* like OBJ_HUMAN; only its shadow is drawn (first person) */
OBJ_TREE, /* size.x = canopy diameter, size.y = trunk height */
OBJ_HOUSE, /* size = (length, wall height, width), with windows/doors */
OBJ_BARN, /* size = (length, wall height, width). PALETTE_WARM: brick barn;
farm halls: PALETTE_GROUND plain, PALETTE_STANDARD red roof,
PALETTE_MODERN solar roof */
OBJ_BOTTLE, /* beer, size = (diameter, height, -); drinkable */
OBJ_VODKA, /* like OBJ_BOTTLE, much stronger */
OBJ_AXE, /* size.y = length; fells trees, takes branches off, cuts logs */
OBJ_SHEARS, /* size.y = length; takes branches off */
OBJ_CHAINSAW, /* fells, takes branches off and cuts, fast */
OBJ_LOG, /* size = (diameter, length, -), lying along its length; from a tree */
OBJ_BRANCH, /* size.y = length; cut off a tree */
OBJ_WATER, /* water bottle: thirst, fresh again; no alcohol */
OBJ_APPLE, /* size.x = diameter; food */
OBJ_BREAD, /* size = loaf; food */
OBJ_SUPPLY, /* static: a crate of apples (PALETTE_WARM) or a water barrel
(PALETTE_MODERN); clicking it hands you one */
OBJ_PUDDLE, /* sick on the ground, size = (radius, seconds until dried up, -); no collision.
work = how fresh (1 .. 0). (Water and pee soak into the ground: wetness.h) */
OBJ_FIREWOOD, /* split wood, size = (diameter of the log, length, parts):
parts 2 = a half, 4 = a quarter */
OBJ_STINK, /* stink lines, size.x = radius; work = how strong (0..1). Over sick, or
(variant 1) over pee in the ground: as strong as the pee there */
OBJ_DECAL, /* static: something painted on the ground (roads, water); mesh given */
OBJ_WOODPILE, /* static: two sleepers where firewood gets stacked, size = (length, -, depth) */
OBJ_FIREPLACE, /* static: a ring of stones, size.x = diameter. Wood lying in it is fuel;
fuel = kg of wood in it, burning = lit (see camp.h) */
OBJ_SAUSAGE, /* size.y = length; food, best grilled */
OBJ_TRASH, /* litter, palette: PALETTE_WARM paper, PALETTE_MODERN a can,
PALETTE_STANDARD plastic, PALETTE_GROUND a broken bit of junk;
size.x < 0: a cigarette butt */
OBJ_BAG, /* garbage bag; stored = pieces of trash in it */
OBJ_BIN, /* static: a big waste container, size = box; trash and bags go in */
OBJ_BUSH, /* static: a round bush, size = (diameter, height, -) */
OBJ_FURNITURE, /* static: variant = FurnitureKind, size = box (see Object_createFurniture) */
OBJ_DOG, /* a dog (see dog.h); name, speech and state of its own */
OBJ_HOSE, /* the nozzle of a garden hose; the hose runs to hose_tap */
OBJ_CAN, /* a watering can; water = liters in it */
OBJ_LADDER, /* a telescopic ladder: slides out (extend) and leans against things */
OBJ_STONE, /* a loose stone, size = bounding box; hard: glass breaks on it */
OBJ_STUMP, /* static: what's left of a felled tree, size = (diameter, height, -);
work = how far it's been chopped out (see tools.h) */
OBJ_TAPE, /* a roll of duct tape: mends a melted hose (see hose.h) */
OBJ_URINELLA, /* (only in pockets - a box of them is an OBJ_SUPPLY that dispenses these) */
OBJ_WALL, /* static, invisible: a solid box of a building made of parts (walls, floors, steps);
size = box, position = its bottom middle; variant 1: a locked door (name says which) */
OBJ_STRUCTURE, /* static: how a building made of parts looks (one mesh, no collision: see OBJ_WALL) */
OBJ_TOY, /* Alice's toys: weight 0 = a ball (size.x across), 1 = a rope to bite (size.x long, size.y thick) */
OBJ_CLOTHES, /* somebody's pullover put down (see clothes.h): variant = ClothLay; no collision */
OBJ_CAR, /* static (moved by hand while it drives): your estate car, size = (width, height, length), nose to +Z;
what's in its boot: load (see car.h) */
OBJ_CRATE, /* a crate of bottles: weight 0 = beer (CRATE_BEER bottles), 1 = water (CRATE_WATER); stored = bottles in it */
OBJ_GEAR, /* camping things: variant = GearKind (see car.h), owner = whose */
OBJ_TENT, /* static: a dome tent, weight 0 small / 1 big (see tent.h); stored = pegs in */
OBJ_UMBRELLA, /* an umbrella: size.y long (folded); opens held in the rain (umbrella_open); variant = colour */
OBJ_HAT, /* a hat off somebody's head (blown off): variant = HAT_*, look.hat_color, owner = whose */
OBJ_STAGE, /* static: a floor's stage being built (world/stage.h): variant = Project, build_stage, build_work */
OBJ_MATERIAL, /* building material from the hardware store: variant = MaterialKind (weight given) */
OBJ_SCYTHE, /* the scythe: mows the Kartoffelacker's grass (world/field.h); carried in one hand */
OBJ_SNAIL, /* a vineyard snail: variant 0 out there, 1 let go at the refuge (weight given: the variant) */
OBJ_SCULPTURE, /* static: a log carved into a figure with the chainsaw (Kerry); size = (diameter, height, -), variant = which */
OBJ_ROPE, /* the throw line for the big tree: a little bag with a long cord coiled to it (thrown up over a branch) */
} ObjectType;
/* Building material (OBJ_MATERIAL): what the stages are built with besides the logs. */
typedef enum { MATERIAL_BOARDS, MATERIAL_NAILS, MATERIAL_SCREWS, MATERIAL_PAINT, MATERIAL_KINDS } MaterialKind;
/* What a body needs over the day. All 0..1; 0 is fine (stamina: 1 is fine). */
typedef struct {
float stamina; /* 1 = fresh .. 0 = exhausted; work drains it, rest brings it back */
float hunger;
float thirst;
float bladder;
float sleepiness;
} Needs;
/* Oriented box collider. */
typedef struct {
Vec3 center; /* local, relative to the pivot (before rotation) */
Vec3 half_extents;
Vec3 tilt; /* local rotation (radians, Y then X then Z) */
Vec3 offset; /* cached: world center relative to the object position */
Vec3 axes[3]; /* cached: world-space orientation */
} Collider;
#define OBJECT_MAX_COLLIDERS 3
#define BOTTLE_SIPS 5 /* a full bottle of beer, water, soda or mate */
#define UMBRELLA_LENGTH 0.9f /* m, folded */
#define UMBRELLA_RADIUS 0.55f /* m across the open canopy */
#define POCKET_URINELLAS 4 /* disposable Urinellas a pocket holds (one-time use) */
#define LIGHTER_USES 60 /* a full lighter lights this many times */
#define POUCH_ROLLUPS 75 /* a pouch of tobacco rolls about this many */
#define PAPERS_PACK 50 /* rolling papers in a packet */
#define FILTERS_BAG 120 /* filter tips in a bag */
/* A pull up in progress (people/climb.c): from where, onto where, over which edge. */
typedef struct {
float t, time; /* how far (0..1 over time seconds) */
Vec3 from, to, edge;
Vec3 across; /* along the edge (the hands hold it a shoulder width apart) */
float hang; /* feet this high while hanging on before the pull up */
float face; /* how far ahead of where it started the face of it is (m) */
Vec3 ankle0[2], toe0[2]; /* where the feet were when it started (eased from there) */
bool sit_way; /* the careful way up something hip high: turn round, sit on it, legs up, stand up ... */
bool sit_now; /* ... sitting on it right now (the body sits: see world.c) ... */
float yaw0; /* ... facing the ledge when it started (rotation.y) */
float swing; /* ... which way round the legs come up (+1 / -1) */
bool belly_way; /* chest high, not so sporty (or drunk): a push up onto the belly, lying over the edge, a knee up, stand up ... */
float belly; /* ... lying over it this much right now (0..1: the body bends over, see world.c) */
bool roll_way; /* ... (drunk) not a knee up after it, but down flat on the top and rolled over onto it (Body_rollOnto) */
} ClimbMove;
typedef struct Object {
ObjectType type;
Palette palette; /* as made (Object_create) ... */
float make_arg; /* ... and the weight it was made with (crates, tents, gear: which one) */
int scene_id; /* made by the scene (1..): saves find it again by this ... */
Vec3 spawn; /* ... and where it was made ... */
ObjectType spawn_type; /* ... as what */
float cloth_gap; /* clothes: hung over an edge this thick */
Vec3 position; /* base point (bottom center) */
Vec3 rotation; /* Euler radians, applied Y, X, Z */
Vec3 pivot; /* mesh origin relative to position */
bool has_home; /* tools: where they belong (the tool room), put back there by careful people */
Vec3 home_spot, home_rot;
Mesh mesh; /* empty for characters, they are drawn as figures */
Collider colliders[OBJECT_MAX_COLLIDERS];
int collider_count;
bool is_static; /* never moves */
bool is_character; /* walks; may step onto low ledges, tramples grass */
float step_height;
float weight;
float strength;
Vec3 velocity;
Vec3 angular_velocity;
Vec3 movement; /* walk velocity requested this frame */
bool is_grounded;
bool on_terrain; /* stood on the terrain during the last step */
float ground_speed; /* horizontal speed during the last step */
bool is_held; /* carried: no physics until dropped */
Vec3 size; /* as created (trees: trunk height left after a cut) */
int sips; /* drinks / bites left (bottles, food) */
float alcohol; /* drunkenness per sip for an average person (bottles) */
float quench; /* thirst taken away per sip */
float nourish; /* hunger taken away per bite */
float refresh; /* stamina given back per sip / bite */
ObjectType dispenses; /* supplies: what you get from it */
struct CarLoad *load; /* cars: what's in the boot (malloc'd, freed with the car) */
bool boot_open; /* cars: the boot lid up */
Mesh inside; /* cars: what you see of it from the driver's seat */
bool keep; /* trees: may not be cut down (round the meadow behind your garages); a tent bag: packed on purpose (its owner leaves it packed) */
float wake; /* drinks: sleepiness off per sip (mate, cola) */
bool rain_out; /* characters: out in the rain (no roof over them) */
bool lives_here; /* characters: the house is theirs (Kurti and his sons): in and out of it */
float indoors; /* characters: inside the house this many more seconds (hidden: see ai.c goInside) */
struct Object *owner; /* camping gear, tents: whose ... */
struct Object *owner2; /* ... tents: and who shares it */
int crate_empties; /* crates: of the bottles in it (stored), this many are empties put back ... */
unsigned char crate_slot[CRATE_SLOTS];
struct Object *umbrella_guest; /* people: somebody under their umbrella with them (the canopy leans their way) ... */
float umbrella_guest_t; /* ... kept up by them this long */
bool umbrella_open; /* umbrellas: open (held up in the rain) */
float umbrella_flip; /* umbrellas: s left blown inside out by a gust (0: as it should be) ... */
int umbrella_flips; /* ... how often that happened ... */
int hats_lost; /* people: how often the wind took their cap (they pull it down tighter each time) */
bool umbrella_ruined; /* ... once too often (or in a storm): the ribs bent, it's no use any more */ /* ... and what's in each slot (CRATE_SLOT: kind and sips; see car.c Crate_*) */
int tent_stage; /* tents: TentStage ... */
float tent_work; /* ... how far the stage is (0..1) ... */
float tent_idle; /* ... seconds since anybody worked on it */
float tent_blown; /* tents: seconds since the wind last pushed it about (0: not lately) */
float smoke_t; /* fireplaces: till the next puff of smoke */
int tent_beds; /* ... sleeping bags (bit 0 owner, 2 owner2) and mats (1, 3) put in */
bool tent_dragged; /* ... being moved (no pegs in): nobody works on it meanwhile */
bool tent_down; /* ... being taken down: the stages backwards, then packed into its bag */
struct Object *in_tent; /* characters: sleeping in this tent (no collisions with it) */
bool rain_nap; /* in their tent out of the rain, dozing: not woken by being rested, up when it stops */
struct Object *riding; /* characters: sitting in this car (hidden, no physics, no AI: see car.c) ... */
int ride_seat; /* ... on this seat (0 the driver) */
int branches; /* trees: branches left on the crown */
int stored; /* woodpiles: pieces stacked on it; firewood: 1 = lies on a woodpile */
float work; /* trees and logs: work done on the current job (see tools.h) */
float cut_at; /* logs: where the current cut is */
Vec3 mark_at, mark_out; /* trees, logs, stumps: where they're being cut, and outwards there (object space) ... */
float mark; /* ... how far along (0 = no mark) */
Vec3 fall_dir; /* trees: direction the top falls */
Vec3 fell_plan; /* trees: which way it should come down (room for it there; zero: not looked yet) ... */
bool fell_blocked; /* ... no room anywhere round it */
float fall_base_y; /* trees: where it pivots falling over (the cut) ... */
Vec3 fall_origin; /* ... from here ... */
float fall_ground_y; /* ... and the ground it comes down on at the end (its butt slides off the stump) */
float fall_slide; /* ... this far along fall_dir */
struct Object *stump; /* trees: the stump left behind (the trunk may touch it) */
struct Object *stink; /* puddles: the smell over it */
bool lifted; /* carried by a team: no gravity, moved by their hands */
bool end_up; /* ... only one end lifted (long and too heavy for them): the other drags on the ground */
Vec3 knock; /* characters: momentum of things that hit them this step */
Vec3 shoved; /* characters: a pushed load is shoving them this way (zero: not) ... */
Vec3 shove_load; /* ... the load's middle */
bool toppled; /* tipped over (bottles) */
float topple; /* 0..1 while falling over */
struct Object *thrown_by; /* set while flying after a throw */
float thrown_time;
float impact; /* speed lost in collisions during the last step */
struct Object *touched; /* the last thing it ran into during the last step (NULL: none, or the ground) */
struct Object *standing_on; /* characters: what they stood on in the last step (NULL: the ground) */
Vec3 scramble_hand; /* characters: up a steep bank, a hand put down on it here (world.c scrambleHand) ... */
bool scrambling; /* ... doing that now */
float veer_side; /* the player: drifting sideways past something lying there (share of the speed, eased) */
bool broken; /* shattered bottle: only shards are left */
int variant; /* trees: 1 = fruit tree; trash: what it is (the palette) */
float fuel; /* fireplaces: kg of wood lying in it */
bool burning; /* fireplaces: lit */
Mesh flames; /* fireplaces: drawn while burning */
Mesh grill_mesh; /* fireplaces: chain and grate hanging from the tripod */
struct Object *on_grill; /* food: lying on this fireplace's grill */
struct Object *moved_to; /* woodpiles: the new one; the firewood here gets carried over */
struct Object *hose_tap; /* hoses: the tap it's connected to */
float water; /* watering cans: liters; fireplaces: liters poured on it (see camp.h) */
bool spraying; /* characters: watering (hose or can) this frame */
float pour; /* characters: 0 = can hanging .. 1 = lifted and tipped, pouring */
bool female; /* characters: squats to pee, unless ... */
bool urinella; /* ... she has one of these (a pack of them) ... */
int urinella_tried; /* women: 0 never tried one, 1 likes it, -1 not for her */
int urinellas; /* ... fresh ones in the pocket (none: she squats like the others, and gets more) */
bool lighter; /* characters: a lighter in the pocket ... */
struct Object *lighter_of;/* ... someone else's (borrowed), or NULL: their own ... */
int lighter_uses; /* ... lights left in it (0: empty) */
int cigarettes; /* characters: ready ones in the pocket (a pack, or roll-ups given) ... */
int tobacco; /* ... tobacco for this many roll-ups (a pouch: POUCH_ROLLUPS) ... */
int papers; /* ... rolling papers (a packet: PAPERS_PACK) ... */
int filters; /* ... filter tips (a bag: FILTERS_BAG) ... */
bool filter_habit; /* ... rolls with a filter (without one they ask for one first) */
bool pocket_tray; /* ... a pocket ashtray (a little tin with a lid) ... */
int pocket_butts; /* ... butts in it (or, without one, wrapped up in the pocket): emptied at a bin, the tin or the fire */
bool butt_held; /* characters: a finished cigarette in the fingers, looking for where it goes (ai.c binButt) */
const char *keys; /* ... keys in the pocket ("Car keys"), or NULL */
bool work_trousers; /* the player: work trousers, more pockets (see Pockets_slots) */
float smoker; /* 0 = doesn't smoke .. 1 = chain smoker: how fast the craving grows */
float craving; /* 0..1: wants a smoke */
float puff_timer; /* smoke breathed out: until the next puff */
float smoke_ask; /* until they ask anybody for a cigarette or a light again */
float dirt; /* characters: 0 = clean .. 1 = filthy (peeing outdoors, lying in the dirt) */
int scrapes; /* characters: shins and knees scraped on things (too fast, or clumsy) */
float scrape_cool; /* (seconds before the next one counts) */
struct Object *toilet; /* characters: inside this toilet right now */
float grill; /* food: seconds over a fire (FOOD_DONE, FOOD_DARK, FOOD_BURNT) */
bool grilled; /* food: done over the fire */
bool burnt; /* food: left on too long, charcoal */
bool sitting; /* characters: squatting, e.g. by the fire */
bool far_off; /* characters: far from the player - feet and hands don't look out for things */
struct Object *seat; /* characters: sitting on this (no collisions with it meanwhile) */
Vec3 sit_at; /* ... stepping over in front of it, turning round and back to here first, */
Vec3 sit_dir; /* ... facing this way */
float sit_yaw; /* ... (as rotation.y) */
bool sit_moving;
bool sit_backing; /* ... turned round, stepping back to the seat */
bool sit_scoot; /* ... sitting, sliding along the bench to sit_at (moving up for somebody) */
int heard_pose; /* characters: the body's pose last frame (going down: a thud) */
bool heard_open; /* gates, the car's boot: open last frame (opening or shutting: a sound) ... */
bool heard_ride; /* ... characters: riding in the car last frame (getting out: its door) */
float rest_time; /* seconds lying still (physics looks less often) */
bool settled; /* ... and turned to lie on the ground under it (see physics: settleOnGround) */
bool climbing; /* characters: pulling themselves up a ledge (no physics meanwhile) */
bool climb_feet; /* ... the feet go here meanwhile (world; set by whoever moves the climb) */
Vec3 climb_ankle[2], climb_toe[2];
ClimbMove climb_move; /* ... how the pull up goes */
/* Stepping over something knee high (walking): a set move, not left to the
feet - the leading leg over, the body over it, the other leg after (Physics) */
float over_t, over_time; /* 0 = not; else how far (0..1) and how long it takes */
Vec3 over_from, over_dir;
float over_near, over_far, over_top; /* its faces along over_dir from over_from, its top over the feet */
int over_lead; /* the foot that goes first */
bool over_up; /* ... up onto it rather than over it */
Vec3 over_foot0[2], over_land[2];
int sit_style; /* characters: SIT_GROUND (cross-legged) or SIT_SEAT */
int cast_id; /* people: who in the story (world/cast.c), -1 nobody of it */
int build_stage; /* a stage (OBJ_STAGE): how far it's built (BuildStage) ... */
float build_work; /* ... person-hours of work into the next bit */
int stock; /* a bought food box (OBJ_SUPPLY): portions left (-1: empty); 0: never runs out (the scene's) */
struct Object *table; /* a bench of a beer table set: its table (sat at facing it, stepped over) */
int snails; /* characters: vineyard snails in their bucket (let go at the refuge) */
bool carving; /* characters: carving with the chainsaw just now (its sound) */
float mowing; /* characters: > 0 mowing with the scythe: where in the swing (rad) */
float commitment; /* people: 0..1 how much they're into their part of the festival */
int guest; /* people: a guest at the festival (which: world/guests.c), 0 none ... */
float fun; /* ... 0..1 how much they enjoy it ... */
int camp_spot; /* ... got to their place at the camping (1; 0 not yet) ... */
bool gone_home; /* ... left on Sunday (out of sight at the gate, nothing more) ... */
bool supporter; /* ... a supporter: a free ticket for two shifts of work (Sunday, the clean-up on Monday) ... */
float clean_sent; /* people: sent to pick up litter at this story hour (game_cleanup.c: not again at once) */
bool heading_home; /* people: off home now (their tent packed, out at the gate: ai_fest.c) - the crew after the clean-up too */
bool storm_told; /* people: told the storm's coming - in under a roof (the festival) */
Vec3 inside_door; /* people: indoors (above), at this door (zero: the main building's) */
int injured; /* people: INJ_* just broken, waiting for the ambulance (lying there) ... */
int injury_side; /* ... which side (0 left, 1 right) ... */
float hospital_until; /* ... away at the hospital till this many story hours (0: not away) ... */
int cast_until; /* ... a cast on (look.cast) till this weekend starts */
float puller; /* people: on the big tree's rope (> 0: their place along it, m from its end) */
int leads, helps; /* people: the Project they lead, one they help with (world/cast.h; PROJECT_NONE 0) */
struct { /* dogs */
int mode;
float timer, phase, wag, lie, bark;
Vec3 goal;
struct Object *fetch; /* after this (thrown, or food lying about) ... */
struct Object *carry; /* ... got it in her mouth ... */
struct Object *from; /* ... thrown by (a stick goes back to them) */
float chew; /* seconds with it (an apple: she keeps it, lies down, eats it) */
float pant, pant_t; /* 0..1 out of breath (after a run, in the midday sun); the breath going on */
Vec3 was; /* where she was last frame: how fast she really goes (not into the car) ... */
float speed, stuck; /* ... m/s; s held up by something in the way ... */
float detour; /* ... s going round it (sign: which way) */
} dog;
float charred; /* wood: 0 = fresh .. 1 = burnt to ashes */
float glow; /* wood: 0..1 glowing embers (in a burning fire) */
float on_fire; /* characters: seconds burning (0 = not) */
float fire_roll; /* characters: seconds rolled on the ground while burning */
float work_rate; /* characters: how fast work goes (liking it, condition); 1 = normal */
float pace; /* people: how quick they walk (1 normal; old and calm: slower) */
float tempo; /* characters: their pace, 1 = normal (0 = not set: normal) */
Vec3 carry_pos; /* characters: where they were last frame ... */
float carry_yaw; /* ... and which way they faced (what they carry didn't hit anything there) */
bool carry_ok; /* ... (known) */
bool carry_blocked; /* this frame: what they carry hit something, so they didn't turn / move */
float skill[ORDER_COUNT]; /* characters: how good at each job (0..1), grows with practice */
int jobs_seen; /* characters: finished tool jobs already counted for practice */
float bump; /* characters: walked into something this fast (m/s) this step ... */
Vec3 bump_normal; /* ... facing away from it */
float bump_top; /* ... its top this high above the feet ... */
bool bump_toe; /* ... a ladder lying there: it hardly moves, the toe hurts */
float bump_cool; /* seconds until a bump counts again */
Vec3 pee_hit; /* characters: where the stream comes down */
float extend, extend_goal; /* ladders: 0 = slid together .. 1 = all the way out */
float raised, raise_goal; /* ladders carried slid out: held near the foot, this steep up in front (radians, 0 = carried at the side) */
bool dipped; /* ... tipped down flat to get under something (a beam, a doorway) */
bool steep; /* ... stood up straight: a wall in front (flat it would go into it) */
float grip_shift; /* ladders carried at the side: slid back (< 0) or on in the hand (m), off a wall */
bool just_caught; /* ladders: fell against something just now and rests there (the game says so) */
struct Object *pullover; /* characters: their pullover as a thing (OBJ_CLOTHES, made the first time it's put down) ... */
bool pullover_down; /* ... lying there (else with them: worn - look.top TOP_JACKET - or tied round the waist) */
bool pullover_sat; /* ... put down as they sat (over the chair's back, under them): taken back getting up */
bool was_sitting; /* characters: sitting last frame (see Clothes_update) */
struct Object *cloth_of; /* clothes: whose */
struct Object *cloth_host;/* clothes: over this chair's back (and along with it when it slides) */
const char *cloth_where; /* clothes: where, said plainly ("over the chair's back") */
bool jacket_told; /* the player: put the pullover on for you / told where it is, this cold spell */
int shown; /* furniture: what its mesh shows (butts in the tin); -1: not built */
bool gate_open; /* gates: open (or opening) ... */
float gate_t; /* ... how far open (0 shut .. 1 open) */
Vec3 hinge; /* ... where it turns */
Vec3 gate_shut, gate_out; /* ... the way it reaches shut, and open (flat, unit) */
Vec3 tucked; /* chairs: where it stands pushed in (set when first pulled out) ... */
bool tucked_set;
bool trunk_cut;
float snag; /* fallen trees: seconds its branches have been caught on something while dragged */ /* trees: felled (cut off its foot: a sawn end, no roots) */
float chair_out, chair_goal; /* ... pulled back from there this far (m), and going to this far */
bool seat_scooted;
bool drop_tip; /* bottles: dropped (not set down): it falls over when it lands, mostly */ /* characters: sitting, the chair shuffled in to the table */
bool leaning; /* ladders: leaning against something (stands still) */
float air_fall; /* characters: in the air, falling this fast at most (m/s; for the landing) */
Vec3 last_ground; /* characters: where they last stood on something (fell through anyway: back there) */
float sprain; /* characters: game s left limping on a twisted ankle (world/injury.c) */
float like; /* people: 0..1 how much they like you (friendship; people/touch.c) ... */
float love; /* ... 0..1 how drawn to you they are (closeness, more) ... */
struct Object *led_by; /* ... walking along with this one, hand in hand (or arm in arm) */
float harass_t; /* people: game s till they might bother somebody again (the festival's drunk ones) */
float ladder_skill; /* characters: practice climbing ladders one-handed (0..1) ... */
float ladder_wobble; /* ... nearly slipped: the next slip is a fall (seconds this counts) */
Vec3 lean_normal; /* ladders: away from what it leans on */
bool spot_checked; /* wood: somebody looked whether there's room to work on it (once) */
float chill; /* characters: 0..1 cold (night, away from a fire): a jacket on over 0.6 */
float shake; /* ladders: wobbling (seconds left) */
float stability; /* ladders: how steady it stands, leaning (0..1; somebody holding it: steady) */
struct Object *held_by; /* ladders: somebody holding it steady at its foot (beside it, hold_side: +1 / -1 along
cross(lean_normal, up), out of the climber's way) ... */
float hold_side;
struct Object *holding_ladder; /* characters: ... this one */
float tip, tip_v; /* ladders: falling over: tipped this far from where it stood (rad), this fast ... */
Vec3 tip_from, tip_dir; /* ... from that axis, towards that (horizontal) way */
float lean_top; /* ladders: where along it the edge is (0 = against a face, no getting off) */
float placing; /* ladders: being put up against something: 0 = not, else how far (0..1) ... */
Vec3 place_foot[2], place_axis[2], place_face[2]; /* ... from (carried) to (leaning) */
float place_extend[2], place_top;
struct Object *on_ladder; /* characters: climbing this ladder ... */
float ladder_at; /* ... with the feet this far up along it */
Vec3 ladder_from[4], ladder_to[4]; /* ... feet and hands on their way from rung to rung */
float ladder_t[4];
Vec3 ladder_shift; /* ... the body still this far from its place on it (just got on: eases away) */
float ladder_off; /* ... stepping off at the bottom (0 = not, .. 1 = off), from ladder_off_from */
Vec3 ladder_off_from;
bool ladder_limbs_ok;
/* Characters only */
FigureLook look;
Body body;
Skeleton skeleton; /* solved every frame, figure space */
Hands hands;
Work work_state; /* tool strokes */
Ai ai; /* everybody but the player */
Vec3 move_local; /* walk intent: x = right, z = forward (-1..1) */
float drunk; /* 0 = sober, 1 = passes out */
Mood temperament; /* how this person carries themselves */
Needs needs;
bool passed_out; /* asleep because of drink, not tiredness */
float tolerance; /* how well they hold their drink (1 = average) */
float bladder_size; /* 1 = average; bigger fills slower and takes longer to empty */
float last_drunk;
float burp_timer; /* > 0: a burp is coming */
char name[16];
int main_hand; /* HAND_RIGHT or HAND_LEFT */
float top_speed; /* sprinting flat out, fresh and sober (m/s) */
float fitness; /* characters: how sporty (0..1), whatever the build: quicker, surer, smoother over things */
float wits; /* characters: 0 = slow on the uptake .. 1 = sharp (sees what's wrong and sorts it out) */
float worn; /* characters: worn by the work of the days (0..1): sleep takes it off, a hard day leaves some for the next */
float height_fear; /* characters: 0 = no head for heights needed .. 1 = won't go up a ladder at all */
float jump_speed; /* take-off speed of a standing jump, fresh and sober (m/s) */
float run_speed; /* player: current speed, eased (m/s) */
float sprint_boost; /* player: 0 = jogging .. 1 = flat out (tapping Shift) */
float tap_timer; /* player: seconds since Shift was last pressed */
} Object;
/* Creates an object, its mesh and matching colliders. See ObjectType for size. */
Object *Object_create(ObjectType type, Palette palette, Vec3 position, Vec3 size, float weight);
void Object_destroy(Object *obj);
void Object_setRotation(Object *obj, Vec3 rotation);
/* Recomputes cached collider data from the current rotation. */
void Object_syncColliders(Object *obj);
Mat4 Object_modelMatrix(const Object *obj);
/* Horizontal forward direction (characters face along it). */
Vec3 Object_facing(const Object *obj);
Vec3 Object_colliderCenter(const Object *obj, int index);
/* Distance along a ray (dir: unit) to an oriented box collider centered at
center (world), and the face it enters through; -1 if it misses or starts inside. */
float Collider_ray(const Collider *c, Vec3 center, Vec3 origin, Vec3 dir, Vec3 *normal);
/* The same for collider index of obj, and the face it
enters through (normal, towards the ray); -1 if it misses or starts inside. */
float Object_rayToCollider(const Object *obj, int index, Vec3 origin, Vec3 dir, Vec3 *normal);
/* How far obj's colliders reach from its position at most (a bounding sphere). */
float Object_reach(const Object *obj);
/* Trees: the trunk's wood and the branches (kg). */
float Object_treeWeight(const Object *obj);
/* What pushing or pulling it along takes (kg): its weight; a fallen tree is
dragged (one end on the ground) and its branches catch: easier without them. */
float Object_dragWeight(const Object *obj);
/* Characters: up high (on a roof, or well over the ground)? */
bool Object_upHigh(const Object *obj, float ground_y);
/* Characters up high: how careful (0 not at all .. 1 creeping): fear, drink and wits (drunk and dim: careless). */
float Object_caution(const Object *obj);
/* Characters: 1 when fresh, down to 0.5 when exhausted (speed, strength, work). */
float Object_vigor(const Object *obj);
/* How high (m) someone walks up onto something solid (a block, a crate): the sporty
and fresh higher, the unfit, worn out or drunk lower; higher than that they go round. */
float Object_stepUpMost(const Object *obj);
/* A person this tall (m): their body box, how high they step, and how fast their legs carry them
(longer legs: a little quicker) - everything else scales from look.height. */
void Object_setHeight(Object *obj, float height);
/* Worn down by the day (sleepiness, felt by personality, fitness and drink): 0 fresh .. 1 done in. */
float Object_tiredness(const Object *obj);
/* Characters: how fast they can sprint and jump right now (tired or drunk: less). */
float Object_topSpeed(const Object *obj);
float Object_jumpSpeed(const Object *obj);
/* Characters: how much the bladder holds right now (1 = average): smaller when worn out. */
float Object_bladder(const Object *obj);
/* Characters: seconds a pee takes, from how full the bladder is. */
float Object_peeTime(const Object *obj);
/* Characters: name, main hand and body stats from weight and temperament. */
void Object_setPerson(Object *obj, const char *name, int main_hand);
bool Object_isBottle(const Object *obj);
bool Object_isFood(const Object *obj);
/* Litter, an empty bottle or broken glass: something to clean up. */
bool Object_isTrash(const Object *obj);
/* Wood that burns: firewood, branches, short logs. */
bool Object_isFuel(const Object *obj);
/* Goes into the toilet (out of sight) to pee. */
void Object_useToilet(Object *who, Object *toilet);
/* Furniture (static): workbench, stove, car, log bench, ... */
Object *Object_createFurniture(FurnitureKind kind, Vec3 position, Vec3 size, float yaw);
/* Sits down: on the seat if there is one (on its side towards `toward`,
facing that way), else cross-legged on the ground. */
/* Sits down (on seat, or the ground with NULL) facing toward. False: no room
there (somebody sits on that chair, or that spot of the bench or log). */
bool Object_sit(Object *who, Object *seat, Vec3 toward);
/* Room on a bench or a log for who, as near `near` as can be: ROOM_FREE (there is),
ROOM_SCOOT (the others there would move up for it), ROOM_NONE. asked: the
unwilling move up too (they were asked); you never move for anybody. */
enum { ROOM_NONE, ROOM_FREE, ROOM_SCOOT };
int Object_benchRoom(const Object *who, const Object *seat, Vec3 near, bool asked);
/* ... and they do move up (sliding along it): true if there's room now. */
bool Object_benchMakeRoom(const Object *who, Object *seat, Vec3 near, bool asked);
/* Sitting, sliding along the bench (moving up): every frame. */
void Object_scootOnSeat(Object *who, float dt);
/* Who's about (the world each frame): Object_sit keeps people apart. */
void Object_seePeople(Object *const *objects, int count);
/* Sitting down on a seat: steps over and turns round first (true meanwhile). */
bool Object_settleOnSeat(Object *who, float dt);
/* Up again: forgets the seat once clear of it (no bumping into it meanwhile). */
void Object_leaveSeat(Object *who, float dt);
#define CHAIR_PULL 0.38f /* m a chair is pulled out to sit on it */
/* A chair being pulled out or pushed in (towards chair_goal): slides along. */
void Object_slideChair(Object *chair, float dt);
/* A seat (chair, bench) within reach of pos, or NULL. */
Object *Object_seatNear(Object *const *objects, int count, Vec3 pos, float reach);
/* Houses: the front door at x (meters along the ridge from the middle). */
void Object_setDoor(Object *obj, float x);
/* Umbrellas: the mesh open or folded, as umbrella_open says (when that changed). */
void Object_showUmbrella(Object *umbrella);
/* Garbage bags: a new mesh for how full it is. */
void Object_fillBag(Object *bag, float added_weight);
/* Trees: cut through the trunk this high above the ground (the rest stays as
the stump), or take branches off the crown. Rebuild mesh and colliders. */
void Object_cutTrunk(Object *obj, float height);
void Object_setBranches(Object *obj, int branches);
/* Bottles and trees: starts falling over so the top lands in direction dir (horizontal). */
/* A tree's mesh and colliders again from its trunk, crown and branches (after loading a save). */
void Object_rebuildTree(Object *obj);
void Object_topple(Object *obj, Vec3 dir);
/* Turns a fallen tree (or a log) into a log of this length lying along axis,
centered at center. Weight follows from the wood volume. */
void Object_makeLog(Object *obj, Vec3 center, Vec3 axis, float length, float diameter);
/* Turns an object into split firewood (see OBJ_FIREWOOD), lying along axis with
its local Z (the curved side) along up, centered at center. */
void Object_makeFirewood(Object *obj, Vec3 center, Vec3 axis, Vec3 up, float length, float diameter, int parts);
/* Puddles and stink lines lying on uneven ground (size as for Object_create). */
Object *Object_createOnGround(ObjectType type, Palette palette, Vec3 position, Vec3 size, ShapeGround ground);
/* Something lying on the ground (a road, water): a static object around a ready mesh. */
Object *Object_createDecal(Mesh mesh, Vec3 position);
/* A gate leaf (FURN_GATE) turning about its hinge towards gate_open (dt: 0 puts it right there). */
void Object_swingGate(Object *gate, float dt);
/* A building made of parts: its look (the solid parts are OBJ_WALLs of their own). */
Object *Object_createStructure(Mesh mesh, Vec3 position, float yaw, Vec3 size);
/* How bad it smells at pos (0 = fine .. 1 = right over something fresh). */
/* Per-frame index of a few kinds that everybody looks for (the world builds it
at the start of each update; objects are only ever added, so it holds for that
array as long as the count is the same). */
enum { KIND_CHARACTERS, KIND_FIREPLACES, KIND_STINKS, KIND_COUNT };
void Object_indexKinds(Object *const *objects, int count);
/* Those of that kind in objects (*n of them) - or all of objects if not indexed for it. */
Object *const *Object_kind(int kind, Object *const *objects, int count, int *n);
float Object_stinkAt(Object *const *objects, int count, Vec3 pos);
/* Woodpiles: puts a quarter of firewood on the next place of the stack, as
neatly as care (0 = just thrown on .. 1 = exactly in its place). A loose
pile getting high may come down: returns how many pieces slid off. */
int Object_stackFirewood(Object *pile, Object *piece, Object *const *objects, int count, float care);
/* Is this firewood lying on that woodpile? */
bool Object_onPile(const Object *pile, const Object *o);
/* How many pieces of firewood lie on the woodpile right now. */
int Object_pileCount(const Object *pile, Object *const *objects, int count);
/* The cut being made shows where point (world) is: progress 0..1 (0 takes the mark away). */
void Object_markCut(Object *o, Vec3 point, float progress);
/* Hard enough to break glass on: stone, brick and plaster walls, metal. */
bool Object_isHard(const Object *obj);
/* Lowest point of the main collider (world). */
float Object_bottom(const Object *obj);
/* A short line about the object ("Beer - 3 sips left"). */
void Object_describe(const Object *obj, char *out, size_t size);
/* Advances a fall started by Object_topple. */
void Object_advanceTopple(Object *obj, float dt);
/* A bottle of water (OBJ_WATER) made a soft drink: 0 water, 1 cola, 2 orange soda, 3 mate. */
void Object_setDrink(Object *b, int drink);
/* Gone (eaten): no mesh, no collision. */
void Object_useUp(Object *obj);
/* Bottles: turns into shards lying on the ground at ground_y. */
void Object_shatter(Object *obj, float ground_y);
#endif /* WORLD_OBJECT_H */