summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2022-11-30 23:25:35 -0800
committerVito Caputo <vcaputo@pengaru.com>2022-12-02 12:09:43 -0800
commitc87a603089a8dad5122d2cf4abcb99d39c79b164 (patch)
treeaeea784a4ff76fd7e9ddd15db8ee28d605d7aa03 /src
parent1d18b18e06bd0ea38e48265a09d129406a346e87 (diff)
game: respawn babies on a timer, and detect immediate infections
Previously respawned babies could respawn on a virus without becoming infected, and this actually had a calming effect on the late stage of the game which is the opposite of what should be happening as the field fills up with viruses. What would happen is eventually most of the active set of babies would be sitting on viruses and isolated by viruses so they wouldn't likely be resuced, but they also weren't becoming infected despite being on viruses. With this change, baby respawning is handled strictly by a timer, currently every .5s. In that timer handler the number of babies off from the GAME_NUM_BABIES (10 presently) are attempted to be respawned. Any of those which are immediately respawned onto viruses are immediately infected. Then the same thing is revisted on the next timer expiration. So it doesn't try very hard to maintain GAME_NUM_BABIES as alive at all times - this actually becomes impossible when the field is too crowded to even find spots to respawn without infection. Instead, what will happen, is in the end game you just have constant babies respawning and dying every .5s. The gameplay is dramatically different now, and it's potentially too difficult now to actually manage to hoard 256 rolls of TP before dying. I haven't managed it in my testing so far... so the probabilities may need to be revisited again. However, the end game /feels/ much more _right_ after this change. You end up with just tons of viruses and death, and if you've managed to hoard a bunch of toilet paper, it's a grim satirical scene of zero living babies, viruses everywhere, but a happy pile of TP icons. I can only imagine how ridiculous it looks if you manage to actually win and get the animated celebratory wall of TP over the sea of death. Now the dead babies turned viruses just need their own unique sprite showing actual infected corpses instead of the same virus sprite. So it's actually visibly a sea of infected bodies...
Diffstat (limited to 'src')
-rw-r--r--src/game.c76
1 files changed, 60 insertions, 16 deletions
diff --git a/src/game.c b/src/game.c
index 19ec9d4..c26fdad 100644
--- a/src/game.c
+++ b/src/game.c
@@ -54,6 +54,9 @@
#define GAME_ENTITIES_DELAY_MS 20
#define GAME_ENTITIES_TIMER PLAY_TICKS_TIMER1
+#define GAME_NEWBABIES_DELAY_MS 500
+#define GAME_NEWBABIES_TIMER PLAY_TICKS_TIMER6
+
#define GAME_MASK_PROTECTION 3
#define GAME_TV_DELAY_MS 3000
@@ -127,9 +130,11 @@ typedef struct mask_t {
entity_any_t entity;
} mask_t;
-typedef struct baby_t {
+typedef struct baby_t baby_t;
+struct baby_t {
entity_any_t entity;
-} baby_t;
+ baby_t *rescues_next;
+};
typedef struct virus_t {
entity_any_t entity;
@@ -194,6 +199,8 @@ typedef struct game_t {
unsigned teepee_cnt;
teepee_icon_t *teepee_head;
entity_any_t *flashers_on_head, *flashers_off_head;
+ baby_t *rescues_head;
+ unsigned babies_cnt;
adult_t *adult;
tv_t *tv;
@@ -258,16 +265,19 @@ static adult_t * adult_new(game_t *game, stage_t *parent)
}
-static baby_t * baby_new(game_t *game, stage_t *parent)
+static baby_t * baby_new(game_t *game, stage_t *parent, baby_t *rescue)
{
- baby_t *baby;
+ baby_t *baby = rescue;
- baby = pad_get(game->pad, sizeof(entity_t));
- fatal_if(!baby, "unable to allocate baby_t");
+ if (!baby) {
+ baby = pad_get(game->pad, sizeof(entity_t));
+ fatal_if(!baby, "unable to allocate baby_t");
+ baby->entity.type = ENTITY_TYPE_BABY;
+ baby->entity.node = baby_node_new(&(stage_conf_t){ .parent = parent, .name = "baby", .active = 1, .alpha = 1.f }, &game->sars->projection_x, &baby->entity.model_x);
+ baby->entity.scale = GAME_BABY_SCALE;
+ } else
+ stage_set_active(baby->entity.node, 1);
- baby->entity.type = ENTITY_TYPE_BABY;
- baby->entity.node = baby_node_new(&(stage_conf_t){ .parent = parent, .name = "baby", .active = 1, .alpha = 1.f }, &game->sars->projection_x, &baby->entity.model_x);
- baby->entity.scale = GAME_BABY_SCALE;
baby->entity.position.x = randf();
baby->entity.position.y = randf();
entity_update_x(game, &baby->entity);
@@ -519,6 +529,10 @@ static ix2_search_status_t tv_search(void *cb_context, ix2_object_t *ix2_object,
v2f_t delta;
float len;
+ /* skip inactive babies, since rescues can linger inactive til respawned */
+ if (!stage_get_active(entity->any.node))
+ return IX2_SEARCH_MORE_MISS;
+
/* skip held baby */
if (game->adult->holding == entity)
return IX2_SEARCH_MORE_MISS;
@@ -540,7 +554,7 @@ static ix2_search_status_t tv_search(void *cb_context, ix2_object_t *ix2_object,
if (ix2_search_by_aabb(game->ix2, NULL, NULL, &entity->any.aabb_x, baby_search, &search)) {
/* baby hit a virus; infect it and spawn a replacement */
infect_entity(game, entity, "baby-virus");
- (void) baby_new(game, game->babies_node);
+ game->babies_cnt--;
}
return IX2_SEARCH_MORE_HIT;
@@ -569,6 +583,10 @@ static ix2_search_status_t mask_search(void *cb_context, ix2_object_t *ix2_objec
switch (entity->any.type) {
case ENTITY_TYPE_BABY:
+ /* skip inactive babies, since rescues can linger inactive til respawned */
+ if (!stage_get_active(entity->any.node))
+ return IX2_SEARCH_MORE_MISS;
+
if (stage_get_active(game->mask->entity.node))
hat_baby(game, &entity->baby, game->mask);
@@ -604,9 +622,13 @@ static ix2_search_status_t virus_search(void *cb_context, ix2_object_t *ix2_obje
switch (entity->any.type) {
case ENTITY_TYPE_BABY:
+ /* skip inactive babies, since rescues can linger inactive til respawned */
+ if (!stage_get_active(entity->any.node))
+ return IX2_SEARCH_MORE_MISS;
+
/* virus hit a baby; infect it and spawn a replacement */
infect_entity(search->game, entity, "baby-virus");
- (void) baby_new(search->game, search->game->babies_node);
+ search->game->babies_cnt--;
return IX2_SEARCH_MORE_HIT;
@@ -891,10 +913,13 @@ static void game_move_adult(game_t *game, v2f_t *dir)
/* rescued baby */
sfx_play(sfx.baby_rescued);
- game->adult->holding->any.position.x = randf();
- game->adult->holding->any.position.y = randf();
- entity_update_x(game, &game->adult->holding->any);
+ /* make the rescued baby available for respawn reuse */
game->adult->holding->any.flashes_remaining = 0;
+ stage_set_active(game->adult->holding->any.node, 0);
+ game->adult->holding->baby.rescues_next = game->rescues_head;
+ game->rescues_head = &game->adult->holding->baby;
+ game->babies_cnt--;
+
game->adult->holding = NULL;
game->adult->rescues++;
}
@@ -923,6 +948,7 @@ static void reset_game(game_t *game)
game->teepee_cnt = 0;
game->teepee_head = NULL;
game->flashers_on_head = game->flashers_off_head = NULL;
+ game->rescues_head = NULL;
game->tv = tv_new(game, game->game_node);
game->teepee = teepee_new(game, game->game_node);
game->mask = mask_new(game, game->game_node);
@@ -930,8 +956,9 @@ static void reset_game(game_t *game)
for (int i = 0; i < NELEMS(game->viruses); i++)
game->viruses[i] = virus_new(game, game->viruses_node);
- for (int i = 0; i < GAME_NUM_BABIES; i++)
- (void) baby_new(game, game->babies_node);
+ game->babies_cnt = GAME_NUM_BABIES;
+ for (int i = 0; i < game->babies_cnt; i++)
+ (void) baby_new(game, game->babies_node, NULL);
stage_set_active(game->adult->entity.node, 1);
stage_set_active(game->babies_node, 1);
@@ -1097,6 +1124,23 @@ static void game_update(play_t *play, void *context)
game->flashers_on_head = new_on;
}
+ if (play_ticks_elapsed(play, GAME_NEWBABIES_TIMER, GAME_NEWBABIES_DELAY_MS)) {
+ for (unsigned n = GAME_NUM_BABIES - game->babies_cnt; n > 0; n--) {
+ baby_search_t search = { .game = game, .baby = game->rescues_head };
+
+ if (search.baby)
+ game->rescues_head = search.baby->rescues_next;
+
+ search.baby = baby_new(game, game->babies_node, search.baby);
+
+ /* check if the new baby is immediately infected */
+ if (ix2_search_by_aabb(game->ix2, NULL, NULL, &search.baby->entity.aabb_x, baby_search, &search))
+ infect_entity(game, (entity_t *)search.baby, "baby-virus");
+ else
+ game->babies_cnt++;
+ }
+ }
+
break;
}
© All Rights Reserved