Working on location exterior
This commit is contained in:
1 parent
3a73f3fbde
commit
ffd5bd01a4
35 files changed
+72176
-124
No files matched your search
@@ -8,6 +8,7 @@
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <cfloat>
|
||||
@@ -499,6 +500,82 @@ namespace ZL
|
||||
std::cout << "[NAV_EDITOR] Reloaded navigation maps (" << navigationMapPaths.size() << " maps)\n";
|
||||
}
|
||||
|
||||
void Location::gameObjectEditorPlaceTree()
|
||||
{
|
||||
if (!player) return;
|
||||
|
||||
static std::mt19937 rng(std::random_device{}());
|
||||
std::uniform_real_distribution<float> scaleDist(0.8f, 1.2f);
|
||||
std::uniform_real_distribution<float> rotDist(0.0f, 360.0f);
|
||||
|
||||
GameObjectData data;
|
||||
data.name = "editor_tree_" + std::to_string(++editorPlacedObjectCounter);
|
||||
data.texturePath = "resources/w/exterior/tree001.png";
|
||||
data.meshPath = "resources/w/exterior/tree003.txt";
|
||||
data.rotationX = 0.0f;
|
||||
data.rotationY = rotDist(rng);
|
||||
data.rotationZ = 0.0f;
|
||||
data.positionX = player->position.x();
|
||||
data.positionY = player->position.y();
|
||||
data.positionZ = player->position.z();
|
||||
data.scale = scaleDist(rng);
|
||||
|
||||
LoadedGameObject obj = GameObjectLoader::buildLoadedObject(data, renderer, CONST_ZIP_FILE);
|
||||
obj.mesh.data.Move({ data.positionX, data.positionY, data.positionZ });
|
||||
obj.mesh.RefreshVBO();
|
||||
|
||||
gameObjects[data.name] = std::move(obj);
|
||||
editorPlacedObjects.push_back(data);
|
||||
|
||||
std::cout << "[GAME_EDITOR] Placed '" << data.name << "' at ("
|
||||
<< data.positionX << ", " << data.positionZ
|
||||
<< ") scale=" << data.scale << " rotY=" << data.rotationY << "\n";
|
||||
}
|
||||
|
||||
void Location::gameObjectEditorSave()
|
||||
{
|
||||
if (editorPlacedObjects.empty()) {
|
||||
std::cout << "[GAME_EDITOR] No editor-placed objects to save\n";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string baseName;
|
||||
for (int i = 1; ; ++i) {
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "saved_objects%03d", i);
|
||||
baseName = buf;
|
||||
if (!std::filesystem::exists(baseName + ".json")) break;
|
||||
}
|
||||
|
||||
using json = nlohmann::json;
|
||||
json j;
|
||||
j["objects"] = json::array();
|
||||
for (const auto& d : editorPlacedObjects) {
|
||||
json obj;
|
||||
obj["name"] = d.name;
|
||||
obj["texturePath"] = d.texturePath;
|
||||
obj["meshPath"] = d.meshPath;
|
||||
obj["rotationX"] = d.rotationX;
|
||||
obj["rotationY"] = d.rotationY;
|
||||
obj["rotationZ"] = d.rotationZ;
|
||||
obj["positionX"] = d.positionX;
|
||||
obj["positionY"] = d.positionY;
|
||||
obj["positionZ"] = d.positionZ;
|
||||
obj["scale"] = d.scale;
|
||||
j["objects"].push_back(obj);
|
||||
}
|
||||
|
||||
const std::string filename = baseName + ".json";
|
||||
std::ofstream out(filename);
|
||||
if (out.is_open()) {
|
||||
out << j.dump(4);
|
||||
std::cout << "[GAME_EDITOR] Saved " << editorPlacedObjects.size()
|
||||
<< " object(s) to " << filename << "\n";
|
||||
} else {
|
||||
std::cerr << "[GAME_EDITOR] Failed to open " << filename << " for writing\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
InteractiveObject* Location::raycastInteractiveObjects(const Eigen::Vector3f& rayOrigin, const Eigen::Vector3f& rayDir) {
|
||||
if (interactiveObjects.empty()) {
|
||||
@@ -983,6 +1060,37 @@ namespace ZL
|
||||
return navigation->setAreaAvailable(areaName, available);
|
||||
}
|
||||
|
||||
int Location::findNpcIndex(const Character* npc) const
|
||||
{
|
||||
for (int i = 0; i < static_cast<int>(npcs.size()); ++i) {
|
||||
if (npcs[i].get() == npc) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Location::fireBumpCallbacks(Character* mover, Character* standing)
|
||||
{
|
||||
if (mover->isPlayer) {
|
||||
// Player walked into a standing NPC
|
||||
const int idx = findNpcIndex(standing);
|
||||
if (idx < 0) return;
|
||||
auto& cooldown = npcBumpedByPlayerCooldown[idx];
|
||||
if (cooldown <= 0.f) {
|
||||
cooldown = NPC_BUMP_CALLBACK_COOLDOWN;
|
||||
scriptEngine.callNpcBumpedByPlayerCallback(idx);
|
||||
}
|
||||
} else if (standing->isPlayer) {
|
||||
// Moving NPC walked into the standing player
|
||||
const int idx = findNpcIndex(mover);
|
||||
if (idx < 0) return;
|
||||
auto& cooldown = npcBumpsPlayerCooldown[idx];
|
||||
if (cooldown <= 0.f) {
|
||||
cooldown = NPC_BUMP_CALLBACK_COOLDOWN;
|
||||
scriptEngine.callNpcBumpsPlayerCallback(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Location::nudgeCharacterAside(Character* standing, const Eigen::Vector3f& awayFrom)
|
||||
{
|
||||
if (!standing || standing->isPlayer) return;
|
||||
@@ -1093,8 +1201,10 @@ namespace ZL
|
||||
|
||||
if (aWasMoving && !bWasMoving) {
|
||||
nudgeCharacterAside(b, a->position);
|
||||
fireBumpCallbacks(a, b);
|
||||
} else if (bWasMoving && !aWasMoving) {
|
||||
nudgeCharacterAside(a, b->position);
|
||||
fireBumpCallbacks(b, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1188,6 +1298,10 @@ namespace ZL
|
||||
resolveCharacterCollisions();
|
||||
updateDynamicReplans(delta);
|
||||
|
||||
const float deltaS = static_cast<float>(delta) / 1000.f;
|
||||
for (auto& [idx, t] : npcBumpedByPlayerCooldown) t -= deltaS;
|
||||
for (auto& [idx, t] : npcBumpsPlayerCooldown) t -= deltaS;
|
||||
|
||||
// Check if player reached target interactive object
|
||||
if (targetInteractiveObject && player && !targetInteractiveObject->isAnimating) {
|
||||
float distToObject = (player->position - targetInteractiveObject->position).norm();
|
||||
|
||||
Reference in new issue
Block a user