/* This file is part of Minitrem. Minitrem is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Minitrem is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Minitrem. If not, see . */ #include "game.hpp" namespace game { unit_spider_t::unit_spider_t(game::state_t *game) : unit_t(game, UNIT_SPIDER) { size[0] = v2f_t(-0.2f, +0.0f); size[1] = v2f_t(+0.2f, +0.3f); render_size[0] = v2f_t(-0.3f, -0.3f); render_size[1] = v2f_t(+0.3f, +0.3f); cmodel.cflags = CF_BODY_SMALL; move.cflags = CF_SOLID | CF_WATER | CF_BODY_SMALL; name = "Spider"; ignore_waking = false; health = max_health = 4; sleep(); } void unit_spider_t::target_and_attack(void) { unit_t *target; world::trace_t trace; if (game->now < next_targetting) return; target = find_target(world, x, 10.0f, true); if (!target) { have_target = false; return; } // Tell everyone about a new target. if (!have_target) game->hivemind_alert(x, 12.0f, true, target->x); have_target = true; wake_time = game->time; start_moving(target->x); next_targetting = game->now + game->prng.next_float(0.2f, 0.4f); if (next_attack && game->time < next_attack) return; if ((x - target->x).len() >= 1.0f) return; trace = world->ray_v_tiles(x, target->x, CF_SOLID); if (trace.hit) return; target->damage(15, this); assets::spider.bite.play_3d(x); next_attack = game->time + MSEC(500); } void unit_spider_t::on_wake(void) { assets::spider.sounds.play_3d(x); } void unit_spider_t::on_think(void) { if (game->now - wake_time > 10.0) { sleep(); return; } target_and_attack(); if (!have_target && !move.moving) random_walk(); if (!keep_moving(4.0)) { // Try to get unstuck. next_targetting = game->now + 0.6; random_walk(); } } void unit_spider_t::on_damage(unit_t *attacker) { if (health < -5) { assets::fx.gibbing.play_3d(x); game->deletion_list.insert(this); return; } if (health <= 0) { if (!dead) assets::fx.corpse_hit.play_3d(x); return; } assets::spider.sounds.play_3d(x); if (attacker) game->hivemind_alert(x, 12.0f, true, attacker->x); else game->hivemind_alert(x, 12.0f, false, v2f_t(0, 0)); } void unit_spider_t::on_death(void) { game->hivemind_alert(x, 16.0f, false, v2f_t(0, 0)); render_layer = render::LAYER_FLAT; cmodel.cflags = CF_BACKGROUND; assets::spider.sounds.play_3d(x); } void unit_spider_t::render_to(render::state_t *render) { bool moving; moving = move.moving && !move.blocked; if (!dead) render->render(game->now * 20, (moving ? &assets::spider.walking : &assets::spider.idle), render_bounds, move.angle); else render->render(game->now * 20, &assets::spider.dead, render_bounds); unit_t::render_to(render); } }