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/injury.c raw
#include "world/injury.h"
#include "people/hands.h"
#include <math.h>
#define ARM_STRENGTH 0.55f /* a cast on the arm: this much of their strength ... */
#define ARM_TEMPO 0.75f /* ... and of their tempo at work */
#define LEG_SPEED 0.42f /* a cast on the leg: this much of their speed ... */
#define LEG_JUMP 0.35f /* ... and of their jump */
#define SPRAIN_TIME (8.0f * 3600.0f) /* game s limping on a twisted ankle ... */
#define SPRAIN_SPEED 0.6f /* ... this much of their speed ... */
#define SPRAIN_JUMP 0.5f /* ... and jump */
static float dice(World *world) {
world->rng = world->rng * 1664525u + 1013904223u;
return (float)(world->rng >> 8) / 16777216.0f;
}
int Injury_roll(World *world, float chance) {
if (dice(world) >= chance) return INJ_NONE;
return dice(world) < 0.55f ? INJ_LEG : INJ_ARM;
}
bool Injury_break(World *world, Object *who, int kind) {
if (!who || !who->is_character || who->type == OBJ_DOG || kind == INJ_NONE || who->injured || who->hospital_until > 0.0f) return false;
who->injured = kind;
who->injury_side = dice(world) < 0.5f ? 0 : 1;
if (Hands_isGrabbing(who)) Hands_release(who); /* (whatever they held: down) */
for (int h = 0; h < 2; h++) if (who->hands.state[h] != HAND_FREE) Hands_drop(who, h);
if (who->body.pose == POSE_UP) Body_fall(&who->body, Object_facing(who));
who->body.down_time = -1.0f; /* (they stay down: the ambulance) */
who->body.asleep = false;
if (who->type != OBJ_PLAYER) Ai_say(who, kind == INJ_LEG ? "AAARGH! My leg - it's broken!" : "AAARGH! My arm! I heard it crack!");
World_noise(world, NOISE_THUD, who->position, 1.0f);
return true;
}
int Injury_castKind(const Object *who) {
return who->look.cast == 0 ? INJ_NONE : who->look.cast <= 2 ? INJ_ARM : INJ_LEG;
}
void Injury_setCast(Object *who, int kind, int side, bool on) {
int limb = kind == INJ_ARM ? 1 + side : kind == INJ_LEG ? 3 + side : 0;
if (on == (who->look.cast != 0) || limb == 0) return;
float k = on ? 1.0f : -1.0f;
if (kind == INJ_ARM) {
who->strength *= powf(ARM_STRENGTH, k);
who->tempo *= powf(ARM_TEMPO, k);
} else {
who->top_speed *= powf(LEG_SPEED, k);
who->jump_speed *= powf(LEG_JUMP, k);
who->pace *= powf(LEG_SPEED + 0.1f, k);
}
who->look.cast = on ? limb : 0;
}
static void sprainOn(Object *who, bool on) {
float k = on ? 1.0f : -1.0f;
who->top_speed *= powf(SPRAIN_SPEED, k);
who->jump_speed *= powf(SPRAIN_JUMP, k);
who->pace *= powf(SPRAIN_SPEED + 0.15f, k);
}
bool Injury_sprain(World *world, Object *who) {
(void)world;
if (!who || !who->is_character || who->type == OBJ_DOG || who->sprain > 0.0f || who->injured) return false;
who->sprain = SPRAIN_TIME;
sprainOn(who, true);
if (who->type != OBJ_PLAYER) Ai_say(who, "Ow! My ankle - twisted it. That'll be a few hours of limping.");
return true;
}
void Injury_update(Object *who, float game_dt) {
if (who->sprain <= 0.0f) return;
if ((who->sprain -= game_dt) > 0.0f) return;
who->sprain = 0.0f;
sprainOn(who, false);
if (who->type != OBJ_PLAYER) Ai_say(who, "Ankle's fine again.");
}
void Injury_heal(Object *who) {
if (who->sprain > 0.0f) { who->sprain = 0.0f; sprainOn(who, false); }
if (who->look.cast) Injury_setCast(who, Injury_castKind(who), (who->look.cast - 1) % 2, false);
who->cast_until = 0;
if (who->injured) { /* (lying there with it: up again) */
who->injured = INJ_NONE;
who->body.down_time = 0.0f;
}
who->scrapes = 0;
}