bring player inspection back!

This commit is contained in:
Kae 2023-06-30 11:44:42 +10:00
parent 17daee680a
commit ad58a960e4
4 changed files with 68 additions and 19 deletions

View File

@ -1,4 +1,5 @@
#include "StarPlayer.hpp"
#include "StarEncode.hpp"
#include "StarJsonExtra.hpp"
#include "StarRoot.hpp"
#include "StarSongbook.hpp"
@ -102,10 +103,6 @@ Player::Player(PlayerConfigPtr config, Uuid uuid) {
m_techs = make_shared<PlayerTech>();
m_log = make_shared<PlayerLog>();
m_description = strf("This {} seems to have nothing to say for {}self.",
m_identity.gender == Gender::Male ? "guy" : "gal",
m_identity.gender == Gender::Male ? "him" : "her");
setModeType(PlayerMode::Casual);
m_useDown = false;
@ -1524,6 +1521,10 @@ String Player::description() const {
return m_description;
}
void Player::setDescription(String const& description) {
m_description = description;
}
Direction Player::walkingDirection() const {
return m_movementController->movingDirection();
}
@ -2107,6 +2108,19 @@ List<ChatAction> Player::pullPendingChatActions() {
return take(m_pendingChatActions);
}
Maybe<String> Player::inspectionLogName() const {
auto identifier = uniqueId();
if (String* str = identifier.ptr()) {
auto hash = XXH3_128bits(str->utf8Ptr(), str->utf8Size());
return String("Player #") + hexEncode((const char*)&hash, sizeof(hash));
}
return identifier;
}
Maybe<String> Player::inspectionDescription(String const& species) const {
return m_description;
}
float Player::beamGunRadius() const {
return m_tools->beamGunRadius();
}
@ -2228,6 +2242,10 @@ void Player::finalizeCreation() {
m_statusController->resetAllResources();
m_effectEmitter->reset();
m_description = strf("This {} seems to have nothing to say for {}self.",
m_identity.gender == Gender::Male ? "guy" : "gal",
m_identity.gender == Gender::Male ? "him" : "her");
}
bool Player::invisible() const {

View File

@ -53,6 +53,7 @@ class Player :
public virtual ToolUserEntity,
public virtual LoungingEntity,
public virtual ChattyEntity,
public virtual InspectableEntity,
public virtual DamageBarEntity,
public virtual PortraitEntity,
public virtual NametagEntity,
@ -172,6 +173,7 @@ public:
bool forceNude() const;
String description() const override;
void setDescription(String const& description);
List<LightSource> lightSources() const override;
@ -377,6 +379,9 @@ public:
List<ChatAction> pullPendingChatActions() override;
Maybe<String> inspectionLogName() const override;
Maybe<String> inspectionDescription(String const& species) const override;
float beamGunRadius() const override;
bool instrumentPlaying() override;

View File

@ -1,13 +1,13 @@
#ifndef STAR_INSPECTABLE_ENTITY_HPP
#define STAR_INSPECTABLE_ENTITY_HPP
#include "StarTileEntity.hpp"
#include "StarEntity.hpp"
namespace Star {
STAR_CLASS(InspectableEntity);
class InspectableEntity : public virtual TileEntity {
class InspectableEntity : public virtual Entity {
public:
// Default implementation returns true
virtual bool inspectable() const;

View File

@ -77,19 +77,23 @@ float InspectionTool::inspectionLevel(InspectableEntityPtr const& inspectable) c
if (!initialized() || !inspectable->inspectable())
return 0;
float totalLevel = 0;
if (auto tileEntity = as<TileEntity>(inspectable)) {
float totalLevel = 0;
// convert spaces to a set of world positions
Set<Vec2I> spaceSet;
for (auto space : inspectable->spaces())
spaceSet.add(inspectable->tilePosition() + space);
// convert spaces to a set of world positions
Set<Vec2I> spaceSet;
for (auto space : tileEntity->spaces())
spaceSet.add(tileEntity->tilePosition() + space);
for (auto space : spaceSet) {
float pointLevel = pointInspectionLevel(centerOfTile(space));
if (pointLevel > 0 && hasLineOfSight(space, spaceSet))
totalLevel += pointLevel;
for (auto space : spaceSet) {
float pointLevel = pointInspectionLevel(centerOfTile(space));
if (pointLevel > 0 && hasLineOfSight(space, spaceSet))
totalLevel += pointLevel;
}
return clamp(totalLevel / min(spaceSet.size(), m_fullInspectionSpaces), 0.0f, 1.0f);
}
return clamp(totalLevel / min(spaceSet.size(), m_fullInspectionSpaces), 0.0f, 1.0f);
else
return pointInspectionLevel(inspectable->position());
}
float InspectionTool::pointInspectionLevel(Vec2F const& position) const {
@ -116,13 +120,35 @@ InspectionTool::InspectionResult InspectionTool::inspect(Vec2F const& position)
// if there's a candidate InspectableEntity at the position, make sure that entity's total inspection level
// is above the minimum threshold
for (auto entity : world()->atTile<InspectableEntity>(Vec2I::floor(position))) {
auto check = [&](InspectableEntityPtr entity) -> Maybe<InspectionTool::InspectionResult> {
if (entity->inspectable() && inspectionLevel(entity) >= m_minimumInspectionLevel) {
if (m_allowScanning)
return {entity->inspectionDescription(species).value(), entity->inspectionLogName(), entity->entityId()};
return { { entity->inspectionDescription(species).value(), entity->inspectionLogName(), entity->entityId() } };
else
return {entity->inspectionDescription(species).value(), {}, {}};
return { { entity->inspectionDescription(species).value(), {}, {} } };
}
return {};
};
WorldGeometry geometry = world()->geometry();
for (auto& entity : world()->query<InspectableEntity>(RectF::withCenter(position, Vec2F::filled(FLT_EPSILON)), [&](InspectableEntityPtr const& entity) {
if (entity->entityType() == EntityType::Object)
return false;
else if (!geometry.rectContains(entity->metaBoundBox().translated(entity->position()), position))
return false;
else {
auto hitPoly = entity->hitPoly();
return hitPoly && geometry.polyContains(*hitPoly, position);
}
})) {
if (auto result = check(entity))
return *result;
}
for (auto& entity : world()->atTile<InspectableEntity>(Vec2I::floor(position))) {
if (auto result = check(entity))
return *result;
}
// check the inspection level at the selected tile