Update Healer Man server

This commit is contained in:
phenom committed 2026-09-24 16:42:43 -04:00
1 parent a64b2cb575
commit 71246e5b75
502 files changed
+4245 -19

No files matched your search

@@ -20,10 +20,15 @@
#include "Rune Engine/Rune/Scene/Base/RuEntityContainer.h"
#include "Rune Engine/Rune/Scene/Base/RuHierarchy_GR2.h"
#include "Rune Engine/Rune/Scene/Controller/RuController_Hierarchy.h"
#include "Rune Engine/Rune/Scene/Controller/RuController_EventTrigger.h"
#include "Rune Engine/Rune/Scene/Controller/RuController_Particle_Emitter.h"
#include "Rune Engine/Rune/Scene/Controller/RuController_Particle_Visualizer_Sprite.h"
#include "Rune Engine/Rune/Scene/Terrain/RuWorld_Base.h"
#include "Rune Engine/Rune/Scene/Terrain/RuWorld_EntitySystem.h"
#include "Rune Engine/Rune/Helper/RuHelper_Entity.h"
#include "Rune Engine/Rune/Scene/Paperdoll/RuEntityPaperdoll.h"
#include "Rune Engine/Rune/Scene/Particle/RuEntity_Particle_Emitter.h"
#include "Rune Engine/Rune/Scene/Particle/RuEntity_Particle_Visualizer_Sprite.h"
#include "Rune Engine/Rune/Engine/Base/RuMaterialBase.h"
#include "Rune Engine/Rune/Engine/Geometry/RuMeshBase.h"
@@ -1434,11 +1439,269 @@ namespace
INT32 m_nextUvIndex;
INT32 m_nextNormalIndex;
};
double FiniteFxValue(double value)
{
return std::isfinite(value) ? value : 0.0;
}
void WriteFxVector(std::ostream &out, const CRuVector3 &value)
{
out << "[" << FiniteFxValue(value.x) << "," << FiniteFxValue(value.y)
<< "," << FiniteFxValue(value.z) << "]";
}
void WriteFxRealTrack(std::ostream &out, CRuAnimTrack<REAL> &track)
{
out << "[";
for(INT32 index = 0; index < track.GetNumKeys(); ++index)
{
REAL time = 0.0f, value = 0.0f;
track.GetKeyTimeByIndex(index, &time);
track.GetKeyByIndex(index, &value);
if(index) out << ",";
out << "{\"time\":" << FiniteFxValue(time) << ",\"value\":" << FiniteFxValue(value) << "}";
}
out << "]";
}
void WriteFxColorTrack(std::ostream &out, CRuAnimTrack<CRuColor4> &track)
{
out << "[";
for(INT32 index = 0; index < track.GetNumKeys(); ++index)
{
REAL time = 0.0f;
CRuColor4 value;
track.GetKeyTimeByIndex(index, &time);
track.GetKeyByIndex(index, &value);
if(index) out << ",";
out << "{\"time\":" << FiniteFxValue(time) << ",\"value\":["
<< FiniteFxValue(value.m_r) << "," << FiniteFxValue(value.m_g) << ","
<< FiniteFxValue(value.m_b) << "," << FiniteFxValue(value.m_a) << "]}";
}
out << "]";
}
void CollectFxSprites(CRuEntity *entity, std::vector<CRuEntity_Particle_Visualizer_Sprite *> &sprites,
std::vector<std::string> &unsupported)
{
if(!entity) return;
entity->UpdateTransformation();
if(entity->GetType().IsSubClassOf(CRuEntity_Particle_Visualizer_Sprite::Type()))
sprites.push_back(static_cast<CRuEntity_Particle_Visualizer_Sprite *>(entity));
else if(entity->GetType().IsSubClassOf(IRuEntity_Particle_Visualizer::Type()))
unsupported.push_back(entity->GetType().GetTypeName());
CRuEntity *child = entity->GetFirstChild();
while(child)
{
CollectFxSprites(child, sprites, unsupported);
child = child->GetNextSibling();
}
}
void WriteFxControllerTrack(std::ostream &out, IRuEntity_KeyableController *controller, INT32 trackIndex)
{
RuAnimTrackVariant variant;
if(!controller->GetTrackByIndex(trackIndex, variant)) { out << "[]"; return; }
if(CRuAnimTrack<REAL> **track = boost::get<CRuAnimTrack<REAL> *>(&variant))
{ WriteFxRealTrack(out, **track); return; }
if(CRuAnimTrack<CRuColor4> **track = boost::get<CRuAnimTrack<CRuColor4> *>(&variant))
{ WriteFxColorTrack(out, **track); return; }
out << "[";
if(CRuAnimTrack<INT32> **track = boost::get<CRuAnimTrack<INT32> *>(&variant))
{
for(INT32 key = 0; key < (*track)->GetNumKeys(); ++key)
{
REAL time = 0; INT32 value = 0;
(*track)->GetKeyTimeByIndex(key, &time); (*track)->GetKeyByIndex(key, &value);
if(key) out << ",";
out << "{\"time\":" << FiniteFxValue(time) << ",\"value\":" << value << "}";
}
}
else if(CRuAnimTrack<RuParticleEmitterType> **track = boost::get<CRuAnimTrack<RuParticleEmitterType> *>(&variant))
{
for(INT32 key = 0; key < (*track)->GetNumKeys(); ++key)
{
REAL time = 0; RuParticleEmitterType value = static_cast<RuParticleEmitterType>(0);
(*track)->GetKeyTimeByIndex(key, &time); (*track)->GetKeyByIndex(key, &value);
if(key) out << ",";
out << "{\"time\":" << FiniteFxValue(time) << ",\"value\":" << static_cast<INT32>(value) << "}";
}
}
else if(CRuAnimTrack<CRuVector3> **track = boost::get<CRuAnimTrack<CRuVector3> *>(&variant))
{
for(INT32 key = 0; key < (*track)->GetNumKeys(); ++key)
{
REAL time = 0; CRuVector3 value;
(*track)->GetKeyTimeByIndex(key, &time); (*track)->GetKeyByIndex(key, &value);
if(key) out << ",";
out << "{\"time\":" << FiniteFxValue(time) << ",\"value\":"; WriteFxVector(out, value); out << "}";
}
}
out << "]";
}
void WriteFxMotions(std::ostream &out, CRuEntity *entity)
{
CRuACTEntity *actor = entity && entity->GetType().IsSubClassOf(CRuACTEntity::Type())
? static_cast<CRuACTEntity *>(entity) : NULL;
CRuACTTemplate *actorTemplate = actor ? actor->GetTemplate() : NULL;
out << "[";
if(actorTemplate)
for(INT32 motionIndex = 0; motionIndex < actorTemplate->GetNumMotions(); ++motionIndex)
{
CRuACTMotion *motion = actorTemplate->GetMotion(motionIndex);
if(!motion) continue;
if(motionIndex) out << ",";
const char *motionName = motion->GetMotionName();
out << "{\"name\":\"" << JsonEscape(motionName ? motionName : "") << "\",\"id\":"
<< motion->GetMotionID() << ",\"controllers\":[";
bool wroteController = false;
for(INT32 nodeIndex = 0; nodeIndex < motion->GetNumMotionNodes(); ++nodeIndex)
{
CRuACTMotionNode *node = motion->GetMotionNodeByIndex(nodeIndex);
IRuEntity_Controller *base = node ? node->Template_GetController() : NULL;
if(!base) continue;
const bool isSprite = base->GetType().IsSubClassOf(CRuController_Particle_Visualizer_Sprite::Type());
const bool isEmitter = base->GetType().IsSubClassOf(CRuController_Particle_Emitter::Type());
const bool isEventTrigger = base->GetType().IsSubClassOf(CRuController_EventTrigger::Type());
if(wroteController) out << ",";
wroteController = true;
out << "{\"type\":\"" << (isSprite ? "sprite" : isEmitter ? "emitter" : "unsupported")
<< "\",\"sourceType\":\"" << JsonEscape(base->GetType().GetTypeName())
<< "\",\"anchor\":\"" << JsonEscape(node->GetAnchorTarget() ? node->GetAnchorTarget() : "") << "\"";
if(isEventTrigger)
{
CRuController_EventTrigger *trigger = static_cast<CRuController_EventTrigger *>(base);
out << ",\"eventID\":" << trigger->GetEventID()
<< ",\"eventParameter0\":" << trigger->GetEventParameter0()
<< ",\"eventParameter1\":" << trigger->GetEventParameter1()
<< ",\"eventString\":\"" << JsonEscape(trigger->GetEventString() ? trigger->GetEventString() : "") << "\""
<< ",\"eventDuration\":" << FiniteFxValue(trigger->GetEventDuration())
<< ",\"startTime\":" << FiniteFxValue(trigger->GetStartTime());
}
if(isSprite)
{
CRuController_Particle_Visualizer_Sprite *sprite = static_cast<CRuController_Particle_Visualizer_Sprite *>(base);
out << ",\"texture\":\"" << JsonEscape(sprite->GetTextureName() ? sprite->GetTextureName() : "") << "\"";
out << ",\"blendMode\":" << static_cast<INT32>(sprite->GetBlendType())
<< ",\"shader\":\"ruSHADER_PARTICLE_SPRITEEX\""
<< ",\"allowWorldRotation\":" << (sprite->GetAllowWorldRotation() ? "true" : "false")
<< ",\"orientation\":" << static_cast<INT32>(sprite->GetOrientation())
<< ",\"billboardType\":" << static_cast<INT32>(sprite->GetBillboardType())
<< ",\"billboardAxis\":" << static_cast<INT32>(sprite->GetBillboardAxis())
<< ",\"orientToTravel\":" << (sprite->GetOrientToDirectionOfTravel() ? "true" : "false")
<< ",\"randomRotation\":" << (sprite->GetRandomRotation() ? "true" : "false")
<< ",\"tileSizePixels\":[" << sprite->GetSubTextureWidth() << "," << sprite->GetSubTextureHeight() << "]"
<< ",\"frameRate\":" << FiniteFxValue(sprite->GetFrameRate())
<< ",\"frameCount\":" << sprite->GetNumFrames()
<< ",\"quadScale\":"; WriteFxVector(out, sprite->GetQuadScale());
out << ",\"quadOffset\":"; WriteFxVector(out, sprite->GetQuadOffset());
}
if(isEmitter)
{
CRuController_Particle_Emitter *emitter = static_cast<CRuController_Particle_Emitter *>(base);
out << ",\"particlePath\":\"" << JsonEscape(emitter->GetParticlePathName() ? emitter->GetParticlePathName() : "") << "\"";
out << ",\"emitterPath\":\"" << JsonEscape(emitter->GetEmitterPathName() ? emitter->GetEmitterPathName() : "") << "\"";
out << ",\"frameType\":" << static_cast<INT32>(emitter->GetFrameType());
out << ",\"pathFrameType\":" << static_cast<INT32>(emitter->GetParticlePathFrameType());
out << ",\"particleSystemRadius\":" << FiniteFxValue(emitter->GetParticleSystemRadius());
out << ",\"pathRandomMirror\":" << (emitter->GetParticlePathRandomMirror() ? "true" : "false");
out << ",\"pathRandomMirrorPlane\":" << static_cast<INT32>(emitter->GetParticlePathRandomMirrorPlane());
out << ",\"pathRotationAxis\":"; WriteFxVector(out, emitter->GetParticlePathRotationAxis());
out << ",\"pathRotationDeviation\":" << FiniteFxValue(emitter->GetParticlePathRotationDeviation());
out << ",\"pathLoopDelay\":" << FiniteFxValue(emitter->GetParticlePathLoopDelay());
out << ",\"emitterPathFrameType\":" << static_cast<INT32>(emitter->GetEmitterPathFrameType());
out << ",\"emitterPathLoopDelay\":" << FiniteFxValue(emitter->GetEmitterPathLoopDelay());
out << ",\"emitterOrientation\":" << static_cast<INT32>(emitter->GetEmitterOrientation());
out << ",\"prerunTime\":" << FiniteFxValue(emitter->GetEmitterPrerunTime());
}
if(isSprite || isEmitter)
{
IRuEntity_KeyableController *keyable = static_cast<IRuEntity_KeyableController *>(base);
out << ",\"tracks\":[";
for(INT32 trackIndex = 0; trackIndex < keyable->GetNumTracks(); ++trackIndex)
{
if(trackIndex) out << ",";
WriteFxControllerTrack(out, keyable, trackIndex);
}
out << "]";
}
out << "}";
}
out << "]}";
}
out << "]";
}
int WriteFxReport(CRuEntity *entity, const std::string &modelPath, const std::string &outputPath)
{
std::vector<CRuEntity_Particle_Visualizer_Sprite *> sprites;
std::vector<std::string> unsupported;
CollectFxSprites(entity, sprites, unsupported);
std::ofstream out(outputPath.c_str(), std::ios::out | std::ios::trunc);
if(!out) return 6;
out << std::setprecision(9);
out << "{\"schemaVersion\":2,\"sourceModel\":\"" << JsonEscape(modelPath) << "\",\"motions\":";
WriteFxMotions(out, entity);
out << ",\"sprites\":[";
bool wroteSprite = false;
for(std::size_t index = 0; index < sprites.size(); ++index)
{
CRuEntity_Particle_Visualizer_Sprite *sprite = sprites[index];
IRuEntity_Particle_Emitter *sourceEmitter = sprite->GetEmitter();
if(!sourceEmitter || !sourceEmitter->GetType().IsSubClassOf(CRuEntity_Particle_Emitter::Type()))
{
unsupported.push_back("sprite without standard particle emitter");
continue;
}
CRuEntity_Particle_Emitter *emitter = static_cast<CRuEntity_Particle_Emitter *>(sourceEmitter);
if(wroteSprite) out << ",";
wroteSprite = true;
out << "{\"name\":\"" << JsonEscape(sprite->GetObjectName() ? sprite->GetObjectName() : "") << "\"";
out << ",\"texture\":\"" << JsonEscape(sprite->GetTextureName() ? sprite->GetTextureName() : "") << "\"";
out << ",\"blendMode\":" << static_cast<INT32>(sprite->GetBlendType());
out << ",\"billboardType\":" << static_cast<INT32>(sprite->GetBillboardType());
out << ",\"tileSizePixels\":[" << sprite->GetSubTextureWidth() << "," << sprite->GetSubTextureHeight() << "]";
out << ",\"frameRate\":" << FiniteFxValue(sprite->GetFrameRate());
out << ",\"frameCount\":" << sprite->GetNumFrames();
out << ",\"quadScale\":"; WriteFxVector(out, sprite->GetQuadScale());
out << ",\"quadOffset\":"; WriteFxVector(out, sprite->GetQuadOffset());
out << ",\"position\":"; WriteFxVector(out, sprite->GetTranslation(ruFRAMETYPE_WORLD));
out << ",\"maxParticles\":" << emitter->GetMaxParticles();
out << ",\"emitterType\":" << static_cast<INT32>(emitter->GetEmitterType());
out << ",\"emitterPosition\":"; WriteFxVector(out, emitter->GetEmitterPosition());
out << ",\"emitterExtents\":"; WriteFxVector(out, emitter->GetEmitterExtents());
out << ",\"emitterRadius\":" << FiniteFxValue(emitter->GetEmitterRadius());
out << ",\"emissionRate\":" << FiniteFxValue(emitter->GetEmissionRate());
out << ",\"speed\":[" << FiniteFxValue(emitter->GetMinSpeed()) << "," << FiniteFxValue(emitter->GetMaxSpeed()) << "]";
out << ",\"extinction\":[" << FiniteFxValue(emitter->GetMinExtinction()) << "," << FiniteFxValue(emitter->GetMaxExtinction()) << "]";
out << ",\"scale\":[" << FiniteFxValue(emitter->GetMinScale()) << "," << FiniteFxValue(emitter->GetMaxScale()) << "]";
out << ",\"direction\":"; WriteFxVector(out, emitter->GetDirection());
out << ",\"deviation\":" << FiniteFxValue(emitter->GetDeviation());
out << ",\"force0\":"; WriteFxVector(out, emitter->GetForce0());
out << ",\"force1\":"; WriteFxVector(out, emitter->GetForce1());
out << ",\"tracks\":{\"color\":"; WriteFxColorTrack(out, sprite->GetTrack_Color());
out << ",\"alpha\":"; WriteFxRealTrack(out, sprite->GetTrack_Alpha());
out << ",\"scale\":"; WriteFxRealTrack(out, sprite->GetTrack_Scale());
out << ",\"rotationSpeed\":"; WriteFxRealTrack(out, sprite->GetTrack_RotationSpeed());
out << "}}";
}
out << "],\"unsupported\":[";
for(std::size_t index = 0; index < unsupported.size(); ++index)
{
if(index) out << ",";
out << "\"" << JsonEscape(unsupported[index]) << "\"";
}
out << "]}\n";
return out ? 0 : 6;
}
}
int main(int argc, char **argv)
{
const bool wdbReportMode = argc == 4 && std::string(argv[1]) == "--wdb-report";
const bool fxReportMode = argc == 5 && std::string(argv[1]) == "--fx-report";
const bool modelExportMode = argc == 4 || argc == 5;
if(!modelExportMode)
{
@@ -1446,7 +1709,8 @@ int main(int argc, char **argv)
<< "Usage:\n"
<< " runewaker_model_exporter <resource-root> <model-resource-path> <output-directory>\n"
<< " runewaker_model_exporter <resource-root> <model-resource-path> <output-directory> <paperdoll-assembly.tsv>\n"
<< " runewaker_model_exporter --wdb-report <wdb-path> <output-json>\n";
<< " runewaker_model_exporter --wdb-report <wdb-path> <output-json>\n"
<< " runewaker_model_exporter --fx-report <resource-root> <model-resource-path> <output-json>\n";
return 2;
}
@@ -1469,6 +1733,23 @@ int main(int argc, char **argv)
RuShutdown();
return exitCode;
}
if(fxReportMode)
{
const std::string resourceRoot = argv[2];
const std::string modelResourcePath = NormalizeResourcePath(argv[3]);
g_ruResourceManager->SetRootDirectory(resourceRoot.c_str());
CRuEntity *entity = g_ruResourceManager->LoadEntity(modelResourcePath.c_str());
if(!entity)
{
std::cerr << "Unable to load ROS entity: " << modelResourcePath << "\n";
RuShutdown();
return 5;
}
const int exitCode = WriteFxReport(entity, modelResourcePath, argv[4]);
ruSAFE_RELEASE(entity);
RuShutdown();
return exitCode;
}
const std::string resourceRoot = argv[1];
const std::string modelResourcePath = NormalizeResourcePath(argv[2]);