66// Description : Patrol path
77// //////////////////////////////////////////////////////////////////////////
88
9+ #include < regex>
910#include " stdafx.h"
1011#include " patrol_path.h"
1112#include " levelgamedef.h"
13+ #include " ../xrCore/mezz_stringbuffer.h"
1214
1315LPCSTR TEST_PATROL_PATH_NAME = " val_dogs_nest4_centre" ;
1416
1517CPatrolPath::CPatrolPath (shared_str name)
1618{
1719#ifdef DEBUG
18- m_name = name;
20+ m_name = name;
1921#endif
2022}
2123
22- CPatrolPath& CPatrolPath::load_raw (const CLevelGraph* level_graph, const CGameLevelCrossTable* cross,
23- const CGameGraph* game_graph, IReader& stream)
24+ CPatrolPath& CPatrolPath::load_raw (const CLevelGraph* level_graph, const CGameLevelCrossTable* cross, const CGameGraph* game_graph, IReader& stream)
2425{
2526 R_ASSERT (stream.find_chunk (WAYOBJECT_CHUNK_POINTS));
2627 u32 vertex_count = stream.r_u16 ();
2728 for (u32 i = 0 ; i < vertex_count; ++i)
29+ {
2830 add_vertex (CPatrolPoint (this ).load_raw (level_graph, cross, game_graph, stream), i);
31+ }
2932
3033 R_ASSERT (stream.find_chunk (WAYOBJECT_CHUNK_LINKS));
3134 u32 edge_count = stream.r_u16 ();
@@ -40,17 +43,86 @@ CPatrolPath& CPatrolPath::load_raw(const CLevelGraph* level_graph, const CGameLe
4043 return (*this );
4144}
4245
46+ CPatrolPath& CPatrolPath::load_from_config (CInifile* ini_paths, LPCSTR patrol_name)
47+ {
48+ R_ASSERT3 (ini_paths->line_exist (patrol_name, " points" ), " Missing key 'points' in patrol path" , patrol_name);
49+ LPCSTR points_csv = ini_paths->r_string (patrol_name, " points" );
50+ std::vector<std::string> points = splitStringMulti (points_csv, " ," , false , true );
51+
52+ // Keep track of name <-> vertex_id association
53+ std::map<shared_str, u32 > vertex_ids_by_name;
54+
55+ // Add patrol points
56+ for (int idx = 0 ; idx < points.size (); idx++)
57+ {
58+ LPCSTR point_name = points[idx].c_str ();
59+ Msg (" [PP] Reading point %s" , point_name);
60+ add_vertex (CPatrolPoint (this ).load_from_config (ini_paths, patrol_name, point_name), idx);
61+ vertex_ids_by_name.emplace (point_name, idx);
62+ }
63+
64+ // Link patrol points
65+ for (int idx = 0 ; idx < points.size (); idx++)
66+ {
67+ LPCSTR point_name = points[idx].c_str ();
68+
69+ Msg (" [PP] Linking point for %s" , point_name);
70+
71+ // Verify if point has links (links are optional)
72+ shared_str links_csv_key = FormatString (" %s:%s" , point_name, " links" );
73+ if (!ini_paths->line_exist (patrol_name, links_csv_key))
74+ {
75+ continue ;
76+ }
77+
78+ // Get list of vertices to link to
79+ LPCSTR links_csv = ini_paths->r_string (patrol_name, links_csv_key.c_str ());
80+ std::vector<std::string> links = splitStringMulti (links_csv, " ," , false , true );
81+
82+ for (std::string link : links)
83+ {
84+ // Link current point to target points
85+ std::pair<u16 , float > link_info = parse_point_link (patrol_name, link, vertex_ids_by_name);
86+ add_edge (idx, link_info.first , link_info.second );
87+ Msg (" [PP] Linked %d to %d with a probability of %f" , link_info.first , idx, link_info.second );
88+ }
89+ }
90+
91+ vertex_ids_by_name.clear ();
92+
93+ return (*this );
94+ }
95+
96+ std::pair<u32 , float > CPatrolPath::parse_point_link (LPCSTR patrol_name, std::string link, std::map<shared_str, u32 > vertex_ids_by_name)
97+ {
98+ Msg (" [PP] Linking %s" , link.c_str ());
99+
100+ std::regex pattern (" (\\ w+)\\ ((\\ d+)\\ )" );
101+ std::smatch matches;
102+
103+ bool matched = std::regex_search (link, matches, pattern);
104+ R_ASSERT4 (matched, " Bad format for patrol path link" , patrol_name, link.c_str ());
105+
106+ std::string target = matches[1 ].str ();
107+ float prob = std::stof (matches[2 ].str ());
108+
109+ auto I = vertex_ids_by_name.find (target.c_str ());
110+ R_ASSERT4 (I != vertex_ids_by_name.end (), " Patrol point link target does not exist" , patrol_name, target.c_str ());
111+
112+ return std::make_pair ((*I).second , prob);
113+ }
114+
43115CPatrolPath::~CPatrolPath ()
44116{
45117}
46118
47119#ifdef DEBUG
48- void CPatrolPath::load (IReader &stream)
120+ void CPatrolPath::load (IReader &stream)
49121{
50122 inherited::load (stream);
51123 vertex_iterator I = vertices ().begin ();
52124 vertex_iterator E = vertices ().end ();
53125 for ( ; I != E; ++I)
54- (*I).second ->data ().path (this );
126+ (*I).second ->data ().path (this );
55127}
56128#endif
0 commit comments