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 "StarPlayer.hpp"
#include "StarEncode.hpp"
#include "StarJsonExtra.hpp" #include "StarJsonExtra.hpp"
#include "StarRoot.hpp" #include "StarRoot.hpp"
#include "StarSongbook.hpp" #include "StarSongbook.hpp"
@ -102,10 +103,6 @@ Player::Player(PlayerConfigPtr config, Uuid uuid) {
m_techs = make_shared<PlayerTech>(); m_techs = make_shared<PlayerTech>();
m_log = make_shared<PlayerLog>(); 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); setModeType(PlayerMode::Casual);
m_useDown = false; m_useDown = false;
@ -1524,6 +1521,10 @@ String Player::description() const {
return m_description; return m_description;
} }
void Player::setDescription(String const& description) {
m_description = description;
}
Direction Player::walkingDirection() const { Direction Player::walkingDirection() const {
return m_movementController->movingDirection(); return m_movementController->movingDirection();
} }
@ -2107,6 +2108,19 @@ List<ChatAction> Player::pullPendingChatActions() {
return take(m_pendingChatActions); 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 { float Player::beamGunRadius() const {
return m_tools->beamGunRadius(); return m_tools->beamGunRadius();
} }
@ -2228,6 +2242,10 @@ void Player::finalizeCreation() {
m_statusController->resetAllResources(); m_statusController->resetAllResources();
m_effectEmitter->reset(); 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 { bool Player::invisible() const {

View File

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

View File

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

View File

@ -77,19 +77,23 @@ float InspectionTool::inspectionLevel(InspectableEntityPtr const& inspectable) c
if (!initialized() || !inspectable->inspectable()) if (!initialized() || !inspectable->inspectable())
return 0; return 0;
float totalLevel = 0; if (auto tileEntity = as<TileEntity>(inspectable)) {
float totalLevel = 0;
// convert spaces to a set of world positions // convert spaces to a set of world positions
Set<Vec2I> spaceSet; Set<Vec2I> spaceSet;
for (auto space : inspectable->spaces()) for (auto space : tileEntity->spaces())
spaceSet.add(inspectable->tilePosition() + space); spaceSet.add(tileEntity->tilePosition() + space);
for (auto space : spaceSet) { for (auto space : spaceSet) {
float pointLevel = pointInspectionLevel(centerOfTile(space)); float pointLevel = pointInspectionLevel(centerOfTile(space));
if (pointLevel > 0 && hasLineOfSight(space, spaceSet)) if (pointLevel > 0 && hasLineOfSight(space, spaceSet))
totalLevel += pointLevel; 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 { 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 // if there's a candidate InspectableEntity at the position, make sure that entity's total inspection level
// is above the minimum threshold // 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 (entity->inspectable() && inspectionLevel(entity) >= m_minimumInspectionLevel) {
if (m_allowScanning) if (m_allowScanning)
return {entity->inspectionDescription(species).value(), entity->inspectionLogName(), entity->entityId()}; return { { entity->inspectionDescription(species).value(), entity->inspectionLogName(), entity->entityId() } };
else 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 // check the inspection level at the selected tile