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/people/ai_touch.c raw
/*
* People and people (people/touch.h): walking along hand in hand with whoever
* leads them (they hold your hand: Object.led_by); stepping in when somebody
* bothers somebody (game_touch.c sends them: Ai.step_in); and, at the
* festival, the odd drunk guest who gets too close to somebody dancing.
*/
#include <math.h>
#include "people/ai_internal.h"
#include "people/touch.h"
#define LED_SIDE 0.5f /* m beside the one leading them */
#define LED_LOST 3.0f /* m apart: the hand's gone */
#define STEP_REACH 1.3f /* m: near enough to say it */
#define STEP_GIVE_UP 45.0f /* real s on the way: they've gone */
#define HARASS_REACH 0.95f /* m: (people keep a step apart walking up: an arm reaches) */
#define HARASS_AGAIN (2.5f * 3600.0f) /* game s before a told-off one tries it again */
/* Hand in hand: beside them, the hand on theirs, the way they go. */
static bool led(Object *self, float dt) {
Object *by = self->led_by;
if (!by) return false;
int hand = Hands_holding(by, self);
if (hand < 0 || Body_isBusy(&self->body) || flatDistance(by->position, self->position) > LED_LOST) { self->led_by = NULL; return false; }
Vec3 f = Object_facing(by), right = vec3(-f.z, 0.0f, f.x);
float side = hand == HAND_LEFT ? -1.0f : 1.0f; /* (their left hand holds mine: I'm on their left) */
Vec3 spot = vec3_add(by->position, vec3_scale(right, side * LED_SIDE));
self->sitting = false;
Vec3 gap = vec3_sub(spot, self->position);
gap.y = 0.0f;
float d = vec3_length(gap), pace = hypotf(by->velocity.x, by->velocity.z);
if (d > 0.12f || pace > 0.3f) { /* (straight along with them: no way round to find, they're right there) */
Vec3 dir = d > 0.12f ? vec3_scale(gap, 1.0f / d) : f;
if (d > 0.12f && pace > 0.3f) dir = vec3_normalize(vec3_add(vec3_scale(f, pace), vec3_scale(dir, 2.0f * d))); /* (on, and back beside them) */
ai_walk(self, dir, fminf(runSpeed(self), pace + 2.0f * d), dt);
} else { stand(self); turnTowards(self, f, dt); }
int joint = hand == HAND_LEFT ? JOINT_HAND_L : JOINT_HAND_R;
Hands_touch(self, Figure_toWorld(by->position, f, by->skeleton.joints[joint]));
return true;
}
/* Off to tell somebody to stop. */
static bool stepIn(Object *self, Object *const *objects, int count, float dt) {
Ai *ai = &self->ai;
Object *who = ai->step_in;
if (!who) return false;
if ((ai->step_t += dt) > STEP_GIVE_UP || who->indoors > 0.0f || who->gone_home) { ai->step_in = ai->step_for = NULL; return false; }
self->sitting = false;
if (!ai_goToPoint(self, who->position, STEP_REACH, objects, count, dt)) return true;
stand(self);
turnTowards(self, vec3_sub(who->position, self->position), dt);
static const char *const SAY[] = { "Hey! Leave them alone - that's not okay.", "Stop that. Now. Nobody wants that here.",
"Back off - you heard them. Not here, not anywhere." };
Ai_say(self, SAY[(int)(random01(ai) * 3.0f) % 3]);
if (who->type == OBJ_HUMAN) { /* (one of us: they back off) */
who->ai.harass = NULL;
who->harass_t = HARASS_AGAIN;
if (who->ai.speech_time <= 0.0f) Ai_say(who, random01(ai) < 0.5f ? "Alright, alright... sorry." : "Whoa - okay. I'm going.");
who->ai.mode = AI_WANDER;
}
if (ai->step_for && ai->step_for->type == OBJ_HUMAN && ai->step_for->ai.speech_time <= 0.0f) Ai_say(ai->step_for, "Thank you.");
if (ai->step_for && ai->step_for->guest) ai->step_for->fun = fminf(1.0f, ai->step_for->fun + 0.12f); /* (somebody had her back) */
ai->step_in = ai->step_for = NULL;
return true;
}
/* The festival: a drunk guest after somebody dancing. */
static bool bother(Object *self, Object *const *objects, int count, float dt) {
Ai *ai = &self->ai;
self->harass_t = fmaxf(0.0f, self->harass_t - (g_world ? g_world->game_dt : dt));
Object *who = ai->harass;
if (!who) return false;
if ((ai->harass_walk += dt) > 60.0f || who->indoors > 0.0f || who->gone_home || Body_isDown(&who->body)) { ai->harass = NULL; return false; }
self->sitting = false;
self->body.dance_goal = 0.0f;
if (!ai_goToPoint(self, who->position, HARASS_REACH, objects, count, dt)) return true;
Vec3 f = Object_facing(who);
Vec3 at = vec3_add(who->position, vec3_add(vec3_scale(f, -0.12f), vec3(0.0f, 0.85f * who->look.height / 1.75f, 0.0f))); /* (from behind: the bottom) */
Hands_touch(self, at);
Touch_react(g_world, who, self, TOUCH_BUTT);
who->ai.fest_floor = 0; /* (she's off out of it) */
who->ai.fest_time = -120.0f;
self->harass_t = HARASS_AGAIN;
ai->harass = NULL;
return true;
}
/* You've got hold of them (and they let you): they stay, and look at you. */
static bool held(Object *self, Object *const *objects, int count, float dt) {
if (self->led_by) return false;
Object *you = findPlayer(objects, count);
if (!you || Hands_holding(you, self) < 0) return false;
if (self->ai.dodge_t > 0.0f) return false; /* (pulled closer: let them come) */
self->sitting = false;
stand(self);
turnTowards(self, vec3_sub(you->position, self->position), dt);
return true;
}
bool ai_touch(Object *self, Object *const *objects, int count, float dt) {
if (stepIn(self, objects, count, dt)) return true;
if (bother(self, objects, count, dt)) return true;
if (held(self, objects, count, dt)) return true;
return led(self, dt);
}