int crtr_attack(creature * attacker, creature * defender) { int damage, xp; damage = random() % (attacker->attack + 1); damage -= random() % (defender->ac + 1); if (damage < 0) damage = 0; defender->health -= damage; if (defender->health <= 0) { // death comes to us all xp = (defender->level + XP_LEVEL_DIFF) - attacker->level; if (xp < 0) xp = 0; crtr_xp_up(attacker, xp); if (plyr_is_me(defender)) { plyr_ev_death("violence"); } else if (!plyr_is_me(attacker)) { // the player wants the name of what he killed tileof(defender)->crtr = NULL; crtr_free(defender); } return DEAD; } return damage; }
void crtr_step(creature * c, int step) { int dam; int dx = 0, dy = 0; int x, y; zone * z; if (c->step != step) { // stamina upkeep c->stamina -= 1; if (c->stamina <= 0) { if (plyr_is_me(c)) { plyr_ev_death("starvation"); } else { memo("%s dies of starvation", c->f->name); x = c->x; y = c->y; z = c->z; tileof(c)->crtr = NULL; crtr_free(c); zone_update(z, x, y); wrefresh(dispscr); } return; } // ai section if (!plyr_is_me(c)) { // this is pretty ugly if (c->x > world.plyr.x) dx = -1; else if (c->x < world.plyr.x) dx = 1; if (c->y > world.plyr.y) dy = -1; else if (c->y < world.plyr.y) dy = 1; if (PLYR.x == c->x + dx && PLYR.y == c->y + dy) { dam = crtr_attack(c, &PLYR); if (dam) { memo("%s hits you for %d damage", c->f->name, dam); } else { memo("%s misses you", c->f->name); } } else { if (!crtr_move(c, dx, dy) && dx && dy) { if (!crtr_move(c, dx, 0)) { crtr_move(c, 0, dy); } } } } c->step = step; } }
void zone_rm_crtr(zone * z, creature * c) { assert(c->z == z); assert(c == z->crtrs.arr[c->z_ind]); assert(z->crtrs.cnt > c->z_ind); // remove from crtrs list z->crtrs.arr[c->z_ind] = z->crtrs.arr[--z->crtrs.cnt]; ((creature *)z->crtrs.arr[c->z_ind])->z_ind = c->z_ind; // remove from tile assert(tileof(c)->crtr == c); tileof(c)->crtr = NULL; zone_update(c->z, c->x, c->y); if (c->z == PLYR.z) wrefresh(dispscr); c->z = NULL; crtr_free(c); }
// // Right now, only steps the player's zone and updates the time // void step_world(void) { int i; long step, step_diff; action * a; assert(world.plyr.health > 0); if (!world.acts_cnt) { step_diff = 0; } else { step = world.acts->step; assert(step >= world.step); step_diff = step - world.step; world.step = step; // process actions while (world.acts_cnt && world.acts->step == step) { a = pop_action(); assert(a != NULL); if (!a->c->deceased) { switch (a->type) { case ACT_IDLE: trigger_pull(&a->c->on_act_comp, a->c, NULL); break; case ACT_MOVE: crtr_try_move(a->c, a->p.dir.x, a->p.dir.y); break; case ACT_AA_MOVE: crtr_try_aa_move(a->c, a->p.dir.x, a->p.dir.y); break; case ACT_PICKUP: crtr_try_pickup(a->c, a->p.ind); break; case ACT_DROP: crtr_try_drop(a->c, a->p.ind); break; case ACT_CONSUME: crtr_try_consume(a->c, a->p.ind); break; case ACT_EQUIP: crtr_try_equip(a->c, a->p.ind); break; case ACT_THROW: crtr_try_throw(a->c, a->p.throw.ind, a->p.throw.x, a->p.throw.y); break; } } a->c->act = NULL; crtr_free(a->c); free(a); } // update time world.tm.steps += step_diff; while (world.tm.steps >= 6000) { world.tm.steps -= 6000; world.tm.min++; if (world.tm.min >= 60) { world.tm.min -= 60; world.tm.hour++; if (world.tm.hour >= 24) { world.tm.hour -= 24; world.tm.mday++; world.tm.wday = (world.tm.wday + 1) % 7 + 1; if (world.tm.mday > 30 + (world.tm.month & 1)) { world.tm.mday -= 30 + (world.tm.month & 1); world.tm.month++; if (world.tm.month > 12) world.tm.year++; } } } } } // update all zones for (i = 0; i < world.zones.cnt; i++) { zone_step(world.zones.arr[i], step_diff); } }