Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
at long last, the suffering is over
  • Loading branch information
nltp-ashes committed Jun 2, 2024
commit f98057b5d13a7127e51444dc7efc68f44b125c22
12 changes: 12 additions & 0 deletions src/xrCore/log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,15 @@ void CloseLog(void)
LogFile->clear();
xr_delete(LogFile);
}

shared_str FormatString(LPCSTR fmt, ...)
{
va_list mark;
string2048 buf;
va_start(mark, fmt);
int sz = _vsnprintf(buf, sizeof(buf) - 1, fmt, mark);
buf[sizeof(buf) - 1] = 0;
va_end(mark);
if (sz) return shared_str(buf);
return shared_str(0);
}
2 changes: 2 additions & 0 deletions src/xrCore/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ void XRCORE_API FlushLog();
extern XRCORE_API xr_vector<shared_str>* LogFile;
extern XRCORE_API BOOL LogExecCB;

shared_str FormatString(LPCSTR fmt, ...);

#endif
2 changes: 2 additions & 0 deletions src/xrGame/ai_space.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ void CAI_Space::patrol_path_storage_raw(IReader& stream)
xr_delete(m_patrol_path_storage);
m_patrol_path_storage = xr_new<CPatrolPathStorage>();
m_patrol_path_storage->load_raw(get_level_graph(), get_cross_table(), get_game_graph(), stream);
m_patrol_path_storage->load_from_config();
}

void CAI_Space::patrol_path_storage(IReader& stream)
Expand All @@ -207,6 +208,7 @@ void CAI_Space::patrol_path_storage(IReader& stream)
xr_delete(m_patrol_path_storage);
m_patrol_path_storage = xr_new<CPatrolPathStorage>();
m_patrol_path_storage->load(stream);
m_patrol_path_storage->load_from_config();
}

void CAI_Space::set_alife(CALifeSimulator* alife_simulator)
Expand Down
81 changes: 76 additions & 5 deletions src/xrGame/patrol_path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,29 @@
// Description : Patrol path
////////////////////////////////////////////////////////////////////////////

#include <regex>
#include "stdafx.h"
#include "patrol_path.h"
#include "levelgamedef.h"
#include "../xrCore/mezz_stringbuffer.h"

LPCSTR TEST_PATROL_PATH_NAME = "val_dogs_nest4_centre";

CPatrolPath::CPatrolPath(shared_str name)
{
#ifdef DEBUG
m_name = name;
m_name = name;
#endif
}

CPatrolPath& CPatrolPath::load_raw(const CLevelGraph* level_graph, const CGameLevelCrossTable* cross,
const CGameGraph* game_graph, IReader& stream)
CPatrolPath& CPatrolPath::load_raw(const CLevelGraph* level_graph, const CGameLevelCrossTable* cross, const CGameGraph* game_graph, IReader& stream)
{
R_ASSERT(stream.find_chunk(WAYOBJECT_CHUNK_POINTS));
u32 vertex_count = stream.r_u16();
for (u32 i = 0; i < vertex_count; ++i)
{
add_vertex(CPatrolPoint(this).load_raw(level_graph, cross, game_graph, stream), i);
}

R_ASSERT(stream.find_chunk(WAYOBJECT_CHUNK_LINKS));
u32 edge_count = stream.r_u16();
Expand All @@ -40,17 +43,85 @@ CPatrolPath& CPatrolPath::load_raw(const CLevelGraph* level_graph, const CGameLe
return (*this);
}

CPatrolPath& CPatrolPath::load_from_config(CInifile* ini_paths, LPCSTR patrol_name)
{
LPCSTR points_csv = ini_paths->r_string(patrol_name, "points");
std::vector<std::string> points = splitStringMulti(points_csv, ",", false, true);

// Keep track of name <-> vertex_id association
std::map<shared_str, u32> vertex_ids_by_name;

// Add patrol points
for (int idx = 0; idx < points.size(); idx++)
{
LPCSTR point_name = points[idx].c_str();
Msg("[ASHES] Reading point %s", point_name);
add_vertex(CPatrolPoint(this).load_from_config(ini_paths, patrol_name, point_name), idx);
vertex_ids_by_name.emplace(point_name, idx);
}

// Link patrol points
for (int idx = 0; idx < points.size(); idx++)
{
LPCSTR point_name = points[idx].c_str();

Msg("[ASHES] Linking point for %s", point_name);

// Verify if point has links (links are optional)
shared_str links_csv_key = FormatString("%s:%s", point_name, "links");
if (!ini_paths->line_exist(patrol_name, links_csv_key))
{
continue;
}

// Get list of vertices to link to
LPCSTR links_csv = ini_paths->r_string(patrol_name, links_csv_key.c_str());
std::vector<std::string> links = splitStringMulti(links_csv, ",", false, true);

for (std::string link : links)
{
// Link current point to target points
std::pair<u16, float> link_info = parse_point_link(link, vertex_ids_by_name);
add_edge(idx, link_info.first, link_info.second);
Msg("[ASHES] Linked %d to %d with a probability of %f", link_info.first, idx, link_info.second);
}
}

vertex_ids_by_name.clear();

return (*this);
}

std::pair<u32, float> CPatrolPath::parse_point_link(std::string link, std::map<shared_str, u32> vertex_ids_by_name)
{
Msg("[ASHES] Linking %s", link.c_str());

std::regex pattern("(\\w+)\\((\\d+)\\)");
std::smatch matches;

bool matched = std::regex_search(link, matches, pattern);
R_ASSERT2(matched, "Bad format for patrol path link", link);

std::string target = matches[1].str();
float prob = std::stof(matches[2].str());

auto I = vertex_ids_by_name.find(target.c_str());
R_ASSERT2(I != vertex_ids_by_name.end(), "Patrol point link target does not exist", str);

return std::make_pair((*I).second, prob);
}

CPatrolPath::~CPatrolPath()
{
}

#ifdef DEBUG
void CPatrolPath::load (IReader &stream)
void CPatrolPath::load(IReader &stream)
{
inherited::load (stream);
vertex_iterator I = vertices().begin();
vertex_iterator E = vertices().end();
for ( ; I != E; ++I)
(*I).second->data().path (this);
(*I).second->data().path(this);
}
#endif
8 changes: 6 additions & 2 deletions src/xrGame/patrol_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#pragma once

#include "stdafx.h"
#include "graph_abstract.h"
#include "patrol_point.h"

Expand All @@ -33,13 +34,16 @@ class CPatrolPath : public CGraphAbstractSerialize<CPatrolPoint, float, u32>
public:
CPatrolPath(shared_str name = "");
virtual ~CPatrolPath();
CPatrolPath& load_raw(const CLevelGraph* level_graph, const CGameLevelCrossTable* cross,
const CGameGraph* game_graph, IReader& stream);
CPatrolPath& load_raw(const CLevelGraph* level_graph, const CGameLevelCrossTable* cross, const CGameGraph* game_graph, IReader& stream);
CPatrolPath& load_from_config(CInifile* ini_paths, LPCSTR patrol_name);
IC const CVertex* point(shared_str name) const;
template <typename T>
IC const CVertex* point(const Fvector& position, const T& evaluator) const;
IC const CVertex* point(const Fvector& position) const;

private:
std::pair<u32, float> CPatrolPath::parse_point_link(std::string link, std::map<shared_str, u32> vertex_ids_by_name);

#ifdef DEBUG
public:
virtual void load (IReader &stream);
Expand Down
52 changes: 39 additions & 13 deletions src/xrGame/patrol_path_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,15 @@ CPatrolPathStorage::~CPatrolPathStorage()
delete_data(m_registry);
}

void CPatrolPathStorage::load_raw(const CLevelGraph* level_graph, const CGameLevelCrossTable* cross,
const CGameGraph* game_graph, IReader& stream)
void CPatrolPathStorage::load_raw(const CLevelGraph* level_graph, const CGameLevelCrossTable* cross, const CGameGraph* game_graph, IReader& stream)
{
IReader* chunk = stream.open_chunk(WAY_PATROLPATH_CHUNK);

if (!chunk)
return;

u32 chunk_iterator;
for (IReader* sub_chunk = chunk->open_chunk_iterator(chunk_iterator); sub_chunk; sub_chunk = chunk->
open_chunk_iterator(chunk_iterator, sub_chunk))
for (IReader* sub_chunk = chunk->open_chunk_iterator(chunk_iterator); sub_chunk; sub_chunk = chunk->open_chunk_iterator(chunk_iterator, sub_chunk))
{
R_ASSERT(sub_chunk->find_chunk(WAYOBJECT_CHUNK_VERSION));
R_ASSERT(sub_chunk->r_u16() == WAYOBJECT_VERSION);
Expand All @@ -40,14 +38,7 @@ void CPatrolPathStorage::load_raw(const CLevelGraph* level_graph, const CGameLev
m_registry.insert(
std::make_pair(
patrol_name,
&xr_new<CPatrolPath>(
patrol_name
)->load_raw(
level_graph,
cross,
game_graph,
*sub_chunk
)
&xr_new<CPatrolPath>(patrol_name)->load_raw(level_graph, cross, game_graph, *sub_chunk)
)
);
}
Expand Down Expand Up @@ -88,7 +79,7 @@ void CPatrolPathStorage::load(IReader& stream)
VERIFY3(I == m_registry.end(), "Duplicated patrol path found ", *pair.first);

#ifdef DEBUG
pair.second->name (pair.first);
pair.second->name(pair.first);
#endif

m_registry.insert(pair);
Expand All @@ -97,6 +88,41 @@ void CPatrolPathStorage::load(IReader& stream)
chunk->close();
}

void CPatrolPathStorage::load_from_config()
{
// Open patrol_paths.ltx
string_path fname;
FS.update_path(fname, "$game_config$", "patrol_paths.ltx");
CInifile* ini_paths = xr_new<CInifile>(fname, TRUE);

Msg("[ASHES] %s initialized", fname);

// Iterate sections. Each section is a unique patrol path
CInifile::Root& paths = ini_paths->sections();
for (CInifile::Root::iterator i = paths.begin(), ie = paths.end(); i != ie; ++i)
{
// Get patrol path name
LPCSTR patrol_name = (*i)->Name.c_str();

Msg("[ASHES] Reading section %s", patrol_name);

// Assert unique
const_iterator exists = m_registry.find(patrol_name);
R_ASSERT2(exists == m_registry.end(), "Duplicated patrol path found", patrol_name);

// Build CPatrolPath object
CPatrolPath* patrol_path = &xr_new<CPatrolPath>(patrol_name)->load_from_config(ini_paths, patrol_name);

// Insert in registry
PATROL_REGISTRY::value_type pair = std::make_pair(patrol_name, patrol_path);
m_registry.insert(pair);
}

Msg("[ASHES] Done reading patrol paths from configs");

xr_delete(ini_paths);
}

void CPatrolPathStorage::save(IWriter& stream)
{
stream.open_chunk(0);
Expand Down
6 changes: 3 additions & 3 deletions src/xrGame/patrol_path_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ class CPatrolPathStorage : public IPureSerializeObject<IReader, IWriter>
public:
IC CPatrolPathStorage();
virtual ~CPatrolPathStorage();
virtual void load(IReader& stream);
virtual void load(IReader& stream);
virtual void load_from_config();
virtual void save(IWriter& stream);

public:
void load_raw(const CLevelGraph* level_graph, const CGameLevelCrossTable* cross, const CGameGraph* game_graph,
IReader& stream);
void load_raw(const CLevelGraph* level_graph, const CGameLevelCrossTable* cross, const CGameGraph* game_graph, IReader& stream);
IC const CPatrolPath* path(shared_str patrol_name, bool no_assert = false) const;
IC const PATROL_REGISTRY& patrol_paths() const;
};
Expand Down
Loading