/* 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 { static std::string scientist_name(procgen::prng_t *prng) { std::stringstream ss; static const char *names[] = { "Сергей", "Александер", "Василий", "Владимир", "Дмитрий", "Иосиф", "Иван", "Пётр", "Юрий" }; ss << "Проф. "; ss << names[prng->next() % (sizeof(names) / sizeof(names[0]))]; return ss.str(); } unit_scientist_t::unit_scientist_t(game::state_t *game) : unit_t(game, UNIT_SCIENTIST) { size[0] = v2f_t(-0.3f, +0.0f); size[1] = v2f_t(+0.3f, +0.3f); render_size[0] = v2f_t(-0.5f, -1.2f); render_size[1] = v2f_t(+0.5f, +0.3f); cmodel.cflags = CF_BODY; move.cflags = CF_SOLID | CF_BODY | CF_WATER; name = scientist_name(&game->prng); wake(); friendly = true; controllable = true; health = max_health = 15; } static std::string russian_plural(size_t count, const char *nom_sg, const char *gen_sg, const char *gen_pl) { const char *word; if (count >= 10 && count < 20) word = gen_sg; else if (count % 10 == 1) word = nom_sg; else if (count % 10 >= 2 && count % 10 < 5) word = gen_sg; else word = gen_pl; return std::to_string(count) + " " + word; } void unit_scientist_t::gather_crystals(void) { rectf_t rect; world::trace_t trace; bool found = true; deco_t *deco; size_t crystals; if (!move.moving) start_moving(gathering_at); if ((x - gathering_at).len() > 0.5f) return; trace = game->world.ray_v_all(x, gathering_at, CF_SOLID|CF_DECOS, this); if (!trace.hit || !trace.ent || trace.ent->type != ET_DECO) { found = false; goto out; } deco = dynamic_cast(trace.ent); if (deco->type != DECO_CRYSTAL) { found = false; goto out; } crystals = game->prng.next() % 60 + 25; game->crystals += crystals; say("Я собрал " + russian_plural(crystals, "кристалл", "кристалла", "кристаллов") + "."); deco->type = DECO_CRYSTAL_BROKEN; assets::scientist.gather.play_3d(x); if (!last_laugh || game->time - last_laugh > MSEC(750)) { assets::scientist.laugh.play_3d(x); last_laugh = game->time; } out: if (!found) say("Здесь ничего нет!"); gathering = false; gather_marker.reset(); } void unit_scientist_t::on_think(void) { keep_moving(4.0); game->wake_area(x); if (gathering) gather_crystals(); if (!move.moving) move_marker.reset(); if (move.moving && (x - move.last_step).len() > 0.5f) { move.last_step = x; assets::soldier.step_stone.play_3d(x); } } void unit_scientist_t::on_spawn(void) { assets::scientist.laugh.play_3d(x); last_laugh = game->time; } void unit_scientist_t::on_death(void) { cmodel.ignore = true; game->deletion_list.insert(this); game->explosion(x); } void unit_scientist_t::render_to(render::state_t *render) { sf::Color selection_color; render::oriented_sprite_t *body; if (selected == selection_cookie) { if (health == max_health) selection_color = sf::Color::Green; else if (health >= max_health / 2) selection_color = sf::Color::Yellow; else if (dead) selection_color = sf::Color::Black; else selection_color = sf::Color::Red; render->render(0.0, &assets::unit_selected, cmodel.bounds, selection_color); } if (move.moving && !move.blocked) body = &assets::scientist.body_walking; else body = &assets::scientist.body_idle; render->render(game->now * 4, body, render_bounds, move.angle); render->render(game->now * 4, &assets::scientist.head_idle, render_bounds, move.angle); unit_t::render_to(render); } void unit_scientist_t::render_late_to(render::state_t *render) { if (selected == selection_cookie) render->render(0.0, &assets::unit_selected_halo, cmodel.bounds, selection_color); } }