void TileObjectBattleItem::draw(Renderer &r, TileTransform &, Vec2<float> screenPosition,
                                TileViewMode mode, bool visible, int, bool, bool)
{
	// Mode isn't used as TileView::tileToScreenCoords already transforms according to the mode
	std::ignore = mode;

	auto item = this->item.lock();
	if (!item)
	{
		LogError("Called with no owning item object");
		return;
	}
	Vec2<float> transformedScreenPos = screenPosition;
	sp<Image> sprite;
	switch (mode)
	{
		case TileViewMode::Isometric:
			sprite = item->item->type->dropped_sprite;
			transformedScreenPos -= item->item->type->dropped_offset;
			break;
		case TileViewMode::Strategy:
		{
			if (item->falling || !visible)
				break;
			sprite = item->strategySprite;
			transformedScreenPos -= Vec2<float>{4, 4};
			break;
		}
		default:
			LogError("Unsupported view mode");
	}
	if (sprite)
		drawTinted(r, sprite, transformedScreenPos, visible);
}
Exemple #2
0
void TileObjectBattleMapPart::draw(Renderer &r, TileTransform &transform,
                                   Vec2<float> screenPosition, TileViewMode mode, bool visible, int,
                                   bool, bool)
{
	std::ignore = transform;
	// Mode isn't used as TileView::tileToScreenCoords already transforms according to the mode
	auto &type = map_part->type;
	sp<Image> sprite;
	Vec2<float> transformedScreenPos = screenPosition;
	switch (mode)
	{
		case TileViewMode::Isometric:
		{
			int frame = map_part->getAnimationFrame();
			if (frame == -1)
			{
				sprite = type->sprite;
			}
			else
			{
				auto &curType =
				    map_part->alternative_type ? map_part->alternative_type : map_part->type;
				sprite = curType->animation_frames[frame];
			}
			transformedScreenPos -= type->imageOffset;
			break;
		}
		case TileViewMode::Strategy:
			sprite = type->strategySprite;
			// All strategy sprites so far are 8x8 so offset by 4 to draw from the center
			// FIXME: Not true for large sprites (2x2 UFOs?)
			transformedScreenPos -= Vec2<float>{4, 4};
			break;
		default:
			LogError("Unsupported view mode");
	}
	if (sprite)
		drawTinted(r, sprite, transformedScreenPos, visible);
}
void TileObjectBattleUnit::draw(Renderer &r, TileTransform &transform, Vec2<float> screenPosition,
                                TileViewMode mode, bool visible, int currentLevel, bool friendly,
                                bool hostile)
{
	// We never draw non-visible units? Or maybe we do?
	if (!visible)
		return;

	static const int offset_prone = 8;
	static const int offset_large = 32;

	static const std::map<Vec2<int>, int> offset_dir_map = {
	    {{0, -1}, 0}, {{1, -1}, 1}, {{1, 0}, 2},  {{1, 1}, 3},
	    {{0, 1}, 4},  {{-1, 1}, 5}, {{-1, 0}, 6}, {{-1, -1}, 7},
	};

	static const std::map<int, int> offset_prone_map = {
	    {0, offset_prone + 0},  {1, offset_prone + 2},  {2, offset_prone + 6},
	    {3, offset_prone + 8},  {4, offset_prone + 12}, {5, offset_prone + 14},
	    {6, offset_prone + 18}, {7, offset_prone + 20},
	};

	static const int ICON_STANDART = 0;
	static const int ICON_PRONE = 1;
	static const int ICON_LARGE = 2;

	std::ignore = transform;
	auto unit = getUnit();
	if (!unit)
	{
		LogError("Called with no owning unit object");
		return;
	}
	switch (mode)
	{
		case TileViewMode::Isometric:
		{
			int firingAngle = 0;
			if (unit->current_hand_state == HandState::Firing)
			{
				Vec3<float> targetVector = unit->targetTile - owningTile->position;
				Vec3<float> targetVectorZeroZ = {targetVector.x, targetVector.y, 0.0f};
				// Firing angle is 0 for -15..15, +-1  for -30..-15 and 15..30, and 2 for everything
				// else
				firingAngle = (int)((glm::angle(glm::normalize(targetVector),
				                                glm::normalize(targetVectorZeroZ)) *
				                     360.0f / 2.0f / M_PI) /
				                    15.0f);
				if (targetVector.z < 0)
				{
					firingAngle = -firingAngle;
				}
				firingAngle = clamp(firingAngle, -2, 2);
			}
			unit->agent->getAnimationPack()->drawUnit(
			    r, screenPosition, unit->agent->getImagePack(BodyPart::Body),
			    unit->agent->getImagePack(BodyPart::Legs),
			    unit->agent->getImagePack(BodyPart::Helmet),
			    unit->agent->getImagePack(BodyPart::LeftArm),
			    unit->agent->getImagePack(BodyPart::RightArm), unit->displayedItem, unit->facing,
			    unit->current_body_state, unit->target_body_state, unit->current_hand_state,
			    unit->target_hand_state,
			    unit->usingLift ? MovementState::None : unit->current_movement_state,
			    unit->getBodyAnimationFrame(), unit->getHandAnimationFrame(),
			    unit->getDistanceTravelled(), firingAngle, visible);
			break;
		}
		case TileViewMode::Strategy:
		{
			// Dead or non-visible units don't appear on strategy screen
			if (unit->isDead() || !visible)
				break;

			// 0 = enemy, 3 = friendly, 2 = neutral
			int side_offset = friendly ? 3 : (hostile ? 0 : 2);
			// Icon type, 0 = normal, 1 = prone, 2 = large
			int icon_type =
			    unit->isLarge() ? ICON_LARGE : ((unit->current_body_state == BodyState::Prone ||
			                                     unit->target_body_state == BodyState::Prone)
			                                        ? ICON_PRONE
			                                        : ICON_STANDART);
			// Unit facing, in game starts with north (0,-1) and goes clockwise, from 0 to 7
			int facing_offset = offset_dir_map.at(unit->facing);
			// Current level offset, 0 = current 1 = above 2 = below
			int curent_level_offset = currentLevel < 0 ? 2 : (currentLevel > 0 ? 1 : 0);

			switch (icon_type)
			{
				case ICON_STANDART:
					drawTinted(r, unit->strategyImages->at(
					                  side_offset * 120 + curent_level_offset * 40 + facing_offset),
					           screenPosition - Vec2<float>{4, 4}, visible);
					break;
				case ICON_PRONE:
					// Vertical
					if (facing_offset == 0 || facing_offset == 4)
					{
						drawTinted(r, unit->strategyImages->at(
						                  side_offset * 120 + curent_level_offset * 40 +
						                  offset_prone_map.at(facing_offset) + 0),
						           screenPosition - Vec2<float>{4.0f, 8.0f}, visible);
						drawTinted(r, unit->strategyImages->at(
						                  side_offset * 120 + curent_level_offset * 40 +
						                  offset_prone_map.at(facing_offset) + 1),
						           screenPosition - Vec2<float>{4.0f, 0.0f}, visible);
					}
					// Horizontal
					else if (facing_offset == 2 || facing_offset == 6)
					{
						drawTinted(r, unit->strategyImages->at(
						                  side_offset * 120 + curent_level_offset * 40 +
						                  offset_prone_map.at(facing_offset) + 0),
						           screenPosition - Vec2<float>{8.0f, 4.0f}, visible);
						drawTinted(r, unit->strategyImages->at(
						                  side_offset * 120 + curent_level_offset * 40 +
						                  offset_prone_map.at(facing_offset) + 1),
						           screenPosition - Vec2<float>{0.0f, 4.0f}, visible);
					}
					// Diagonal
					else
					{
						drawTinted(r, unit->strategyImages->at(
						                  side_offset * 120 + curent_level_offset * 40 +
						                  offset_prone_map.at(facing_offset) + 0),
						           screenPosition - Vec2<float>{8.0f, 8.0f}, visible);
						drawTinted(r, unit->strategyImages->at(
						                  side_offset * 120 + curent_level_offset * 40 +
						                  offset_prone_map.at(facing_offset) + 1),
						           screenPosition - Vec2<float>{0.0f, 8.0f}, visible);
						drawTinted(r, unit->strategyImages->at(
						                  side_offset * 120 + curent_level_offset * 40 +
						                  offset_prone_map.at(facing_offset) + 2),
						           screenPosition - Vec2<float>{8.0f, 0.0f}, visible);
						drawTinted(r, unit->strategyImages->at(
						                  side_offset * 120 + curent_level_offset * 40 +
						                  offset_prone_map.at(facing_offset) + 3),
						           screenPosition - Vec2<float>{0.0f, 0.0f}, visible);
					}
					break;
				case ICON_LARGE:
					drawTinted(r,
					           unit->strategyImages->at(
					               side_offset * 120 + curent_level_offset * 40 + offset_large + 0),
					           screenPosition - Vec2<float>{8.0f, 8.0f}, visible);
					drawTinted(r,
					           unit->strategyImages->at(
					               side_offset * 120 + curent_level_offset * 40 + offset_large + 1),
					           screenPosition - Vec2<float>{0.0f, 8.0f}, visible);
					drawTinted(r,
					           unit->strategyImages->at(
					               side_offset * 120 + curent_level_offset * 40 + offset_large + 2),
					           screenPosition - Vec2<float>{8.0f, 0.0f}, visible);
					drawTinted(r,
					           unit->strategyImages->at(
					               side_offset * 120 + curent_level_offset * 40 + offset_large + 3),
					           screenPosition - Vec2<float>{0.0f, 0.0f}, visible);
					break;
			}
			break;
		}
		default:
			LogError("Unsupported view mode");
	}
}