#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 #include #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 */