diff options
Diffstat (limited to 'src/game')
| -rw-r--r-- | src/game/game.hpp | 2 | ||||
| -rw-r--r-- | src/game/unit_nest.cpp | 96 | ||||
| -rw-r--r-- | src/game/unit_soldier.cpp | 301 | ||||
| -rw-r--r-- | src/game/unit_spider.cpp | 104 | ||||
| -rw-r--r-- | src/game/units.cpp | 436 | 
5 files changed, 504 insertions, 435 deletions
diff --git a/src/game/game.hpp b/src/game/game.hpp index 331c1d1..517f74a 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -164,6 +164,8 @@ namespace game {  	class fx_move_marker_t; +	unit_t *find_target(world::world_t *world, v2f_t x, float r, bool friendly); +  	class unit_t : public entity_t {  	protected:  		double next_targetting = -INFINITY; diff --git a/src/game/unit_nest.cpp b/src/game/unit_nest.cpp new file mode 100644 index 0000000..326741e --- /dev/null +++ b/src/game/unit_nest.cpp @@ -0,0 +1,96 @@ +/* +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 <http://www.gnu.org/licenses/>. +*/ + +#include "game.hpp" + +namespace game { + + +unit_nest_t::unit_nest_t(game::state_t *game_) : unit_t(game_, UNIT_NEST) +{ +	size[0] = {-0.6f, +0.2f}; +	size[1] = {+0.6f, +0.6f}; +	render_size[0] = {-0.6f, -0.6f}; +	render_size[1] = {+0.6f, +0.6f}; +	cmodel.cflags = CF_BACKGROUND; + +	name = text::get(text::UNIT_NAME_NEST); + +	ignore_waking = false; + +	health = max_health = 45; + +	next_spawning = game->now + 5.0; +} + +void spawn_spider(game::state_t *game, v2f_t nest) +{ +	for (size_t i = 0; i < 5; i++) { // Try a few times before giving up. +		v2f_t offset, x; +		world::cmodel_t cmodel; +		unit_spider_t *spider; +	 +		offset = game->dice_prng.unit_vec2(); +		x = nest + offset * (game->dice_prng.next_float() * 0.2 + 0.4); + +		cmodel.bounds = rectf_t(v2f_t(-0.5f, -0.5f), v2f_t(0.5f, 0.5f)) + x; +		cmodel.cflags = CF_SOLID | CF_WATER | CF_BODY_SMALL; +		if (game->world.test_rect(&cmodel, NULL)) +			continue; + +		spider = new unit_spider_t(game); +		spider->place(&game->world, x); +		return; +	} +} + +void unit_nest_t::on_think(void) +{ +	if (wake_time + 30 > game->now) +		sleep(); + +	if (next_spawning > game->now) +		return; + +	spawn_spider(game, x); +	next_spawning = game->now + game->dice_prng.next_float() * 10 + 5; +} + +void unit_nest_t::on_spawn(void) +{ +	spawn_spider(game, x); +	spawn_spider(game, x); +	spawn_spider(game, x); +} + +void unit_nest_t::on_death(void) +{ +	render_layer = -1; +	cmodel.cflags = CF_BACKGROUND; +} + +void unit_nest_t::render_to(render::state_t *render) +{ +	if (!dead) +		render->render(game->now, &assets::nest.idle, render_bounds); +	else +		render->render(game->now, &assets::nest.dead, render_bounds); + +	unit_t::render_to(render); +} + +} diff --git a/src/game/unit_soldier.cpp b/src/game/unit_soldier.cpp new file mode 100644 index 0000000..152f475 --- /dev/null +++ b/src/game/unit_soldier.cpp @@ -0,0 +1,301 @@ +/* +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 <http://www.gnu.org/licenses/>. +*/ + +#include "game.hpp" + +namespace game { + +unit_soldier_t::unit_soldier_t(game::state_t *game) : unit_t(game, UNIT_SOLDIER) +{ +	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 = text::get(text::UNIT_NAME_SOLDIER); + +	wake(); +	friendly = true; +	controllable = true; + +	health = max_health = 20; +} + +void unit_soldier_t::check_area(void) +{ +	rectf_t bounds; + +	bounds[0] = x - v2f_t(10, 10); +	bounds[1] = x + v2f_t(10, 10); + +	willpower_bonus = 0; +	fear_dc = 0; + +	for (world::entity_t *went : game->world.get_entities(bounds, -1)) { +		auto ent = dynamic_cast<game::entity_t*>(went); +		unit_t *unit; + +		// WTF? +		if (!ent) +			continue; + +		if (ent == this) +			continue; + +		// Wake everything around. +		if (!ent->ignore_waking) { +			ent->wake_time = game->now; + +			if (!ent->awake) +				ent->wake(); +		} + +		if (ent->type != ET_UNIT) +			continue; + +		unit = (unit_t*)ent; + +		if (unit->dead) +			continue; + +		if (unit->friendly) +			willpower_bonus += 6; +		else { +			if (unit->type == UNIT_NEST) +				fear_dc += 6; +			else +				fear_dc += 4; +		} +	} +} + +static v2f_t spread_aim(v2f_t aim, float cof, procgen::prng_t *prng) +{ +	float t; + +	t = prng->next_float(-cof / 2, cof / 2); + +	return v2f_t(cos(t) * aim[0] - sin(t) * aim[1], +	             sin(t) * aim[0] + cos(t) * aim[1]); +} + +void unit_soldier_t::shoot(v2f_t aim) +{ +	v2f_t end; +	world::trace_t trace; +	v2f_t muzzle_point; +	fx_tracer_t *tracer; +	fx_flash_t *flash; + +	end = x + (aim - x).norm() * 40; + +	trace = world->trace(x, end, CF_SOLID); + +	muzzle_point = x + v2f_t(0, -1.0f); + +	tracer = new fx_tracer_t(game, muzzle_point, trace.end); +	tracer->place(&game->world); + +	flash = new fx_flash_t(game, muzzle_point, 5.0f); +	flash->place(&game->world); + +	last_attack = game->now; +	assets::soldier.fire.play_3d(x); +	//target->damage(3, this); FIXME +} + +void unit_soldier_t::target_and_attack(void) +{ +	unit_t *target; +	v2f_t aim; + +	if (manual_firing) { +		aim = manual_firing_target; +		last_target_x = aim; +		goto skip_targetting; +	} + +	if (game->now < next_targetting) +		return; + +	next_targetting = game->now + 0.2; + +	target = find_target(world, x, 5.0f, false); +	if (!target) +		return; +	aim = target->x; + +	last_target_time = game->now; +	last_target_x = target->x; + +skip_targetting: +	if (last_attack + game->dice_prng.next_float(1.4f, 1.6f) > game->now) +		return; + +	shoot(spread_aim(aim, 0.2, &game->dice_prng)); +} + +void unit_soldier_t::on_think(void) +{ +	check_area(); + +	if (panic && game->now > panic_end) { +		move.moving = false; +		move.path.clear(); +		panic = false; +		controllable = true; +	} + +	if (health == max_health) +		willpower_bonus += 3; +	else if (fear_dc > 1 && health < max_health / 2) +		fear_dc += 3; + +	if (!panic && fear_dc > 1 && game->now > next_fear_test) { +		size_t roll; +		bool success; +		std::stringstream ss; + +		roll = game->roll(die_t(20)); +		success = roll + willpower_bonus >= fear_dc; + +		ss << name << " " << text::get(text::UNIT_SAVING_THROW_WILLPOWER); +		ss << ": " << roll << " + " << willpower_bonus << " = " << roll + willpower_bonus; +		ss << " vs " << fear_dc << ": "; + +		if (success) +			ss << text::get(text::UNIT_SAVING_THROW_SUCCESS); +		else +			ss << text::get(text::UNIT_SAVING_THROW_FAILURE); + +		game->interface->print(ss.str()); + +		if (!success) { +			say(text::get(text::SAY_PANIC)); +			panic = true; +			panic_end = game->now + 10; +			panic_turn = -INFINITY; +			controllable = false; +		} +		 +		next_fear_test = game->now + 3; +	} + +	if (!panic) { +		target_and_attack(); + +		keep_moving(2.0); +		if (!move.moving) +			move_marker.reset(); +	} else { +		move.moving = true; +		keep_moving(3.0); + +		if (game->now >= panic_turn) { +			v2f_t t; + +			t = game->dice_prng.unit_vec2(); + +			move.path.clear(); +			move.path.push_back(x + t * 10); +			panic_turn = game->now + 0.3; +		} +	} + +	if (move.moving && (x - move.last_step).len() > 0.5f) { +		move.last_step = x; +		assets::soldier.step_stone.play_3d(x); +	} +} + +void unit_soldier_t::on_death(void) +{ +	render_size[0] = v2f_t(-0.75f, -0.5f); +	render_size[1] = v2f_t(+0.75f, +0.5f); +	render_layer = -1; +	cmodel.cflags = CF_BACKGROUND; +	place(world, x); +	controllable = false; +	game->selected_units.erase(this); +	move_marker.reset(); +} + +void unit_soldier_t::render_to(render::state_t *render) +{ +	sf::Color selection_color; + +	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; + +		if (panic && (game->now - floor(game->now) > 0.5)) +			selection_color = sf::Color::Blue; + +		render->render(0.0, &assets::unit_selected, cmodel.bounds, selection_color); +	} + +	if (!dead) { +		render::oriented_sprite_t *legs, *body; +		float body_angle; + +		if (move.moving && !move.blocked) +			legs = &assets::soldier.legs_walking; +		else +			legs = &assets::soldier.legs_idle; + +		if (!panic && (manual_firing || last_target_time + 3 > game->now)) { +			if (last_attack + 0.1 > game->now) +				body = &assets::soldier.body_firing; +			else +				body = &assets::soldier.body_aiming; + +			body_angle = (last_target_x - x).angle(); + +		} else { +			body = &assets::soldier.body_idle; +			body_angle = move.angle; +		} + +		render->render(game->now * 10, legs, render_bounds, move.angle); + +		if (panic) +			render->render(game->now * 10, &assets::soldier.body_panic, render_bounds); +		else +			render->render(game->now * 10, body, render_bounds, body_angle); + +		render->render(game->now * 10, &assets::soldier.head_idle, render_bounds, body_angle); +	} else +		render->render(game->now * 10, &assets::soldier.dead, render_bounds); + +	unit_t::render_to(render); +} + +void unit_soldier_t::render_late_to(render::state_t *render) +{ +	if (selected == selection_cookie) +		render->render(0.0, &assets::unit_selected_halo, cmodel.bounds, selection_color); +} + +} diff --git a/src/game/unit_spider.cpp b/src/game/unit_spider.cpp new file mode 100644 index 0000000..ed6b0f0 --- /dev/null +++ b/src/game/unit_spider.cpp @@ -0,0 +1,104 @@ +/* +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 <http://www.gnu.org/licenses/>. +*/ + +#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 = text::get(text::UNIT_NAME_SPIDER); + +	ignore_waking = false; + +	health = max_health = 4; +} + +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) +		return; + +	start_moving(target->x); +	next_targetting = game->now + game->dice_prng.next_float(0.2f, 0.4f); + +	if (last_attack + 0.5 > game->now) +		return; + +	if ((x - target->x).len() >= 1.0f) +		return; + +	trace = world->trace(x, target->x, CF_SOLID); +	if (trace.hit) +		return; + +	last_attack = game->now; +	target->damage(15, this); +} + +void unit_spider_t::on_think(void) +{ +	return; + +	target_and_attack(); + +	keep_moving(4.0); + +	if (!move.moving && wake_time + 5 < game->now) +		sleep(); +} + +void unit_spider_t::on_wake(void) +{ +} + +void unit_spider_t::on_death(void) +{ +	render_layer = -1; +	cmodel.cflags = CF_BACKGROUND; +} + +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); +} + +} diff --git a/src/game/units.cpp b/src/game/units.cpp index 63c16db..bbddd93 100644 --- a/src/game/units.cpp +++ b/src/game/units.cpp @@ -222,7 +222,7 @@ void unit_t::die(unit_t *killer)  	on_death();  } -static unit_t *find_target(world::world_t *world, v2f_t x, float r, +unit_t *find_target(world::world_t *world, v2f_t x, float r,                             bool friendly)  {  	rectf_t rect; @@ -257,438 +257,4 @@ static unit_t *find_target(world::world_t *world, v2f_t x, float r,  	return nearest;  } -unit_soldier_t::unit_soldier_t(game::state_t *game) : unit_t(game, UNIT_SOLDIER) -{ -	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 = text::get(text::UNIT_NAME_SOLDIER); - -	wake(); -	friendly = true; -	controllable = true; - -	health = max_health = 20; -} - -void unit_soldier_t::check_area(void) -{ -	rectf_t bounds; - -	bounds[0] = x - v2f_t(10, 10); -	bounds[1] = x + v2f_t(10, 10); - -	willpower_bonus = 0; -	fear_dc = 0; - -	for (world::entity_t *went : game->world.get_entities(bounds, -1)) { -		auto ent = dynamic_cast<game::entity_t*>(went); -		unit_t *unit; - -		// WTF? -		if (!ent) -			continue; - -		if (ent == this) -			continue; - -		// Wake everything around. -		if (!ent->ignore_waking) { -			ent->wake_time = game->now; - -			if (!ent->awake) -				ent->wake(); -		} - -		if (ent->type != ET_UNIT) -			continue; - -		unit = (unit_t*)ent; - -		if (unit->dead) -			continue; - -		if (unit->friendly) -			willpower_bonus += 6; -		else { -			if (unit->type == UNIT_NEST) -				fear_dc += 6; -			else -				fear_dc += 4; -		} -	} -} - -static v2f_t spread_aim(v2f_t aim, float cof, procgen::prng_t *prng) -{ -	float t; - -	t = prng->next_float(-cof / 2, cof / 2); - -	return v2f_t(cos(t) * aim[0] - sin(t) * aim[1], -	             sin(t) * aim[0] + cos(t) * aim[1]); -} - -void unit_soldier_t::shoot(v2f_t aim) -{ -	v2f_t end; -	world::trace_t trace; -	v2f_t muzzle_point; -	fx_tracer_t *tracer; -	fx_flash_t *flash; - -	end = x + (aim - x).norm() * 40; - -	trace = world->trace(x, end, CF_SOLID); - -	muzzle_point = x + v2f_t(0, -1.0f); - -	tracer = new fx_tracer_t(game, muzzle_point, trace.end); -	tracer->place(&game->world); - -	flash = new fx_flash_t(game, muzzle_point, 5.0f); -	flash->place(&game->world); - -	last_attack = game->now; -	assets::soldier.fire.play_3d(x); -	//target->damage(3, this); FIXME -} - -void unit_soldier_t::target_and_attack(void) -{ -	unit_t *target; -	v2f_t aim; - -	if (manual_firing) { -		aim = manual_firing_target; -		last_target_x = aim; -		goto skip_targetting; -	} - -	if (game->now < next_targetting) -		return; - -	next_targetting = game->now + 0.2; - -	target = find_target(world, x, 5.0f, false); -	if (!target) -		return; -	aim = target->x; - -	last_target_time = game->now; -	last_target_x = target->x; - -skip_targetting: -	if (last_attack + game->dice_prng.next_float(1.4f, 1.6f) > game->now) -		return; - -	shoot(spread_aim(aim, 0.2, &game->dice_prng)); -} - -void unit_soldier_t::on_think(void) -{ -	check_area(); - -	if (panic && game->now > panic_end) { -		move.moving = false; -		move.path.clear(); -		panic = false; -		controllable = true; -	} - -	if (health == max_health) -		willpower_bonus += 3; -	else if (fear_dc > 1 && health < max_health / 2) -		fear_dc += 3; - -	if (!panic && fear_dc > 1 && game->now > next_fear_test) { -		size_t roll; -		bool success; -		std::stringstream ss; - -		roll = game->roll(die_t(20)); -		success = roll + willpower_bonus >= fear_dc; - -		ss << name << " " << text::get(text::UNIT_SAVING_THROW_WILLPOWER); -		ss << ": " << roll << " + " << willpower_bonus << " = " << roll + willpower_bonus; -		ss << " vs " << fear_dc << ": "; - -		if (success) -			ss << text::get(text::UNIT_SAVING_THROW_SUCCESS); -		else -			ss << text::get(text::UNIT_SAVING_THROW_FAILURE); - -		game->interface->print(ss.str()); - -		if (!success) { -			say(text::get(text::SAY_PANIC)); -			panic = true; -			panic_end = game->now + 10; -			panic_turn = -INFINITY; -			controllable = false; -		} -		 -		next_fear_test = game->now + 3; -	} - -	if (!panic) { -		target_and_attack(); - -		keep_moving(2.0); -		if (!move.moving) -			move_marker.reset(); -	} else { -		move.moving = true; -		keep_moving(3.0); - -		if (game->now >= panic_turn) { -			v2f_t t; - -			t = game->dice_prng.unit_vec2(); - -			move.path.clear(); -			move.path.push_back(x + t * 10); -			panic_turn = game->now + 0.3; -		} -	} - -	if (move.moving && (x - move.last_step).len() > 0.5f) { -		move.last_step = x; -		assets::soldier.step_stone.play_3d(x); -	} -} - -void unit_soldier_t::on_death(void) -{ -	render_size[0] = v2f_t(-0.75f, -0.5f); -	render_size[1] = v2f_t(+0.75f, +0.5f); -	render_layer = -1; -	cmodel.cflags = CF_BACKGROUND; -	place(world, x); -	controllable = false; -	game->selected_units.erase(this); -	move_marker.reset(); -} - -void unit_soldier_t::render_to(render::state_t *render) -{ -	sf::Color selection_color; - -	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; - -		if (panic && (game->now - floor(game->now) > 0.5)) -			selection_color = sf::Color::Blue; - -		render->render(0.0, &assets::unit_selected, cmodel.bounds, selection_color); -	} - -	if (!dead) { -		render::oriented_sprite_t *legs, *body; -		float body_angle; - -		if (move.moving && !move.blocked) -			legs = &assets::soldier.legs_walking; -		else -			legs = &assets::soldier.legs_idle; - -		if (!panic && (manual_firing || last_target_time + 3 > game->now)) { -			if (last_attack + 0.1 > game->now) -				body = &assets::soldier.body_firing; -			else -				body = &assets::soldier.body_aiming; - -			body_angle = (last_target_x - x).angle(); - -		} else { -			body = &assets::soldier.body_idle; -			body_angle = move.angle; -		} - -		render->render(game->now * 10, legs, render_bounds, move.angle); - -		if (panic) -			render->render(game->now * 10, &assets::soldier.body_panic, render_bounds); -		else -			render->render(game->now * 10, body, render_bounds, body_angle); - -		render->render(game->now * 10, &assets::soldier.head_idle, render_bounds, body_angle); -	} else -		render->render(game->now * 10, &assets::soldier.dead, render_bounds); - -	unit_t::render_to(render); -} - -void unit_soldier_t::render_late_to(render::state_t *render) -{ -	if (selected == selection_cookie) -		render->render(0.0, &assets::unit_selected_halo, cmodel.bounds, selection_color); -} - -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 = text::get(text::UNIT_NAME_SPIDER); - -	ignore_waking = false; - -	health = max_health = 4; -} - -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) -		return; - -	start_moving(target->x); -	next_targetting = game->now + game->dice_prng.next_float(0.2f, 0.4f); - -	if (last_attack + 0.5 > game->now) -		return; - -	if ((x - target->x).len() >= 1.0f) -		return; - -	trace = world->trace(x, target->x, CF_SOLID); -	if (trace.hit) -		return; - -	last_attack = game->now; -	target->damage(15, this); -} - -void unit_spider_t::on_think(void) -{ -	return; - -	target_and_attack(); - -	keep_moving(4.0); - -	if (!move.moving && wake_time + 5 < game->now) -		sleep(); -} - -void unit_spider_t::on_wake(void) -{ -} - -void unit_spider_t::on_death(void) -{ -	render_layer = -1; -	cmodel.cflags = CF_BACKGROUND; -} - -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); -} - -unit_nest_t::unit_nest_t(game::state_t *game_) : unit_t(game_, UNIT_NEST) -{ -	size[0] = {-0.6f, +0.2f}; -	size[1] = {+0.6f, +0.6f}; -	render_size[0] = {-0.6f, -0.6f}; -	render_size[1] = {+0.6f, +0.6f}; -	cmodel.cflags = CF_BACKGROUND; - -	name = text::get(text::UNIT_NAME_NEST); - -	ignore_waking = false; - -	health = max_health = 45; - -	next_spawning = game->now + 5.0; -} - -void spawn_spider(game::state_t *game, v2f_t nest) -{ -	for (size_t i = 0; i < 5; i++) { // Try a few times before giving up. -		v2f_t offset, x; -		world::cmodel_t cmodel; -		unit_spider_t *spider; -	 -		offset = game->dice_prng.unit_vec2(); -		x = nest + offset * (game->dice_prng.next_float() * 0.2 + 0.4); - -		cmodel.bounds = rectf_t(v2f_t(-0.5f, -0.5f), v2f_t(0.5f, 0.5f)) + x; -		cmodel.cflags = CF_SOLID | CF_WATER | CF_BODY_SMALL; -		if (game->world.test_rect(&cmodel, NULL)) -			continue; - -		spider = new unit_spider_t(game); -		spider->place(&game->world, x); -		return; -	} -} - -void unit_nest_t::on_think(void) -{ -	if (wake_time + 30 > game->now) -		sleep(); - -	if (next_spawning > game->now) -		return; - -	spawn_spider(game, x); -	next_spawning = game->now + game->dice_prng.next_float() * 10 + 5; -} - -void unit_nest_t::on_spawn(void) -{ -	spawn_spider(game, x); -	spawn_spider(game, x); -	spawn_spider(game, x); -} - -void unit_nest_t::on_death(void) -{ -	render_layer = -1; -	cmodel.cflags = CF_BACKGROUND; -} - -void unit_nest_t::render_to(render::state_t *render) -{ -	if (!dead) -		render->render(game->now, &assets::nest.idle, render_bounds); -	else -		render->render(game->now, &assets::nest.dead, render_bounds); - -	unit_t::render_to(render); -} -  } // namespace game  | 
