#include "people/pockets.h" #include bool Pockets_light(Object *who) { if (!who->lighter || who->lighter_uses <= 0) return false; who->lighter_uses--; return true; } Object *Pockets_lighterNear(Object *who, Object *const *objects, int count, float range) { Object *best = NULL; for (int i = 0; i < count; i++) { Object *o = objects[i]; if (o == who || !o->is_character || o->type == OBJ_DOG || !o->lighter || o->lighter_uses <= 0) continue; float d = hypotf(o->position.x - who->position.x, o->position.z - who->position.z); if (d < range) { range = d; best = o; } } return best; } void Pockets_passLighter(Object *from, Object *to) { if (!from->lighter || to->lighter) return; to->lighter = true; to->lighter_uses = from->lighter_uses; to->lighter_of = from->lighter_of == to ? NULL : from->lighter_of ? from->lighter_of : from; /* (back home: their own again) */ from->lighter = false; from->lighter_of = NULL; from->lighter_uses = 0; } bool Pockets_giveBack(Object *who) { Object *owner = who->lighter_of; if (!who->lighter || !owner || owner->lighter) return false; Pockets_passLighter(who, owner); return true; } int Pockets_refill(Object *who) { int got = POCKET_URINELLAS - who->urinellas; if (got < 0) got = 0; who->urinellas = POCKET_URINELLAS; return got; } static bool canRoll(const Object *who) { return who->tobacco > 0 && who->papers > 0; } bool Pockets_hasSmoke(const Object *who) { return who->cigarettes > 0 || canRoll(who); } bool Pockets_takeSmoke(Object *who, bool can_roll, bool *rolled) { if (canRoll(who) && (can_roll || who->cigarettes <= 0)) { if (!can_roll) return false; /* (only the makings, and no hands for rolling) */ who->tobacco--; who->papers--; if (who->filters > 0) who->filters--; /* (with a filter if there's one) */ *rolled = true; return true; } if (who->cigarettes <= 0) return false; who->cigarettes--; *rolled = false; return true; } Object *Pockets_smokesNear(Object *who, Object *const *objects, int count, float range) { Object *best = NULL; for (int i = 0; i < count; i++) { Object *o = objects[i]; if (o == who || !o->is_character || o->type == OBJ_DOG || !Pockets_hasSmoke(o)) continue; float d = hypotf(o->position.x - who->position.x, o->position.z - who->position.z); if (d < range) { range = d; best = o; } } return best; } bool Pockets_giveSmoke(Object *from, Object *to) { if (from->cigarettes > 0) from->cigarettes--; else if (canRoll(from)) { from->tobacco--; from->papers--; if (from->filters > 0) from->filters--; } /* (rolls them one) */ else return false; to->cigarettes++; return true; } PocketNeed Pockets_need(const Object *who) { if (who->cigarettes > 0 || (who->tobacco <= 0 && who->papers <= 0)) return POCKET_NOTHING; if (who->papers <= 0) return POCKET_PAPERS; if (who->tobacco <= 0) return POCKET_TOBACCO; if (who->filter_habit && who->filters <= 0) return POCKET_FILTERS; return POCKET_NOTHING; } static int spare(const Object *o, PocketNeed what) { switch (what) { case POCKET_PAPERS: return o->papers; case POCKET_FILTERS: return o->filters; case POCKET_TOBACCO: return o->tobacco; case POCKET_ASHTRAY: return o->pocket_tray ? 2 : 0; case POCKET_NOTHING: break; } return 0; } Object *Pockets_hasNear(Object *who, PocketNeed what, Object *const *objects, int count, float range) { Object *best = NULL; for (int i = 0; i < count; i++) { Object *o = objects[i]; if (o == who || !o->is_character || o->type == OBJ_DOG || spare(o, what) <= 1) continue; float d = hypotf(o->position.x - who->position.x, o->position.z - who->position.z); if (d < range) { range = d; best = o; } } return best; } int Pockets_give(Object *from, Object *to, PocketNeed what) { static const int SOME[] = { [POCKET_NOTHING] = 0, [POCKET_PAPERS] = 3, [POCKET_FILTERS] = 5, [POCKET_TOBACCO] = 2, [POCKET_ASHTRAY] = 1 }; int n = spare(from, what); if (n > SOME[what]) n = SOME[what]; if (n <= 0) return 0; switch (what) { case POCKET_PAPERS: from->papers -= n; to->papers += n; break; case POCKET_FILTERS: from->filters -= n; to->filters += n; break; case POCKET_TOBACCO: from->tobacco -= n; to->tobacco += n; break; case POCKET_ASHTRAY: if (!to->butt_held) return 0; to->butt_held = false; from->pocket_butts++; break; case POCKET_NOTHING: break; } return n; } const char *Pockets_needName(PocketNeed what) { switch (what) { case POCKET_PAPERS: return "a paper"; case POCKET_FILTERS: return "a filter"; case POCKET_TOBACCO: return "a bit of tobacco"; case POCKET_ASHTRAY: return "your pocket ashtray"; case POCKET_NOTHING: break; } return "something"; } int Pockets_slots(const Object *who) { switch (who->look.garment) { case GARMENT_TROUSERS: return who->work_trousers ? 8 : 4; /* (work trousers: thigh and leg pockets too) */ case GARMENT_SHORTS: return 4; case GARMENT_SKIRT: return 2; default: return 1; /* (a dress: one small one) */ } } int Pockets_used(const Object *who) { return (who->cigarettes > 0) + (who->tobacco > 0) + (who->papers > 0) + (who->filters > 0) + (who->lighter ? 1 : 0) + (who->keys ? 1 : 0) + (who->urinellas > 0) + (who->pocket_tray || who->pocket_butts > 0); } void Pockets_keepButt(Object *who) { who->pocket_butts++; who->butt_held = false; }