File: ConversationKeyExtractor.cpp

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (136 lines) | stat: -rw-r--r-- 3,284 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include "ConversationKeyExtractor.h"

#include "itextstream.h"

#include <regex>

#include "string/convert.h"
#include "string/predicate.h"
#include "ConversationCommand.h"
#include "ConversationCommandLibrary.h"

namespace conversation 
{

ConversationKeyExtractor::ConversationKeyExtractor(ConversationMap& map) :
	_convMap(map),
	_regexConvNum("conv_(\\d+)_(.*)"), 
	_regexConvCmd("cmd_(\\d+)_(.*)")
{
	assert(_convMap.empty());
}

void ConversationKeyExtractor::operator()(const std::string& key, const std::string& value) 
{
	// Quick discard of any non-conversation keys
	if (!string::starts_with(key, "conv")) return;

	// Extract the conv index
	std::smatch results;
	if (!std::regex_match(key, results, _regexConvNum)) 
	{
		// No match, abort
		return;
	}

	// Get the conversation number
	int num = string::convert<int>(results[1].str());

	// We now have the conversation number and the substring (everything after
	// "conv_<n>_" which applies to this conversation.
	std::string convSubString = results[2];

	// Switch on the substring
	if (convSubString == "name") 
	{
		_convMap[num].name = value;
	}
	else if (convSubString == "talk_distance") 
	{
		_convMap[num].talkDistance = string::convert<float>(value, 60);
	}
	else if (convSubString == "actors_must_be_within_talkdistance")
	{
		_convMap[num].actorsMustBeWithinTalkdistance = (value == "1");
	}
	else if (convSubString == "actors_always_face_each_other_while_talking")
	{
		_convMap[num].actorsAlwaysFaceEachOther = (value == "1");
	}
	else if (convSubString == "max_play_count")
	{
		_convMap[num].maxPlayCount = string::convert<int>(value, -1);
	}
	else if (convSubString.substr(0, 6) == "actor_")
	{
		// This is an actor definition, extract the number
		int actorNum = string::convert<int>(convSubString.substr(6), -1);

		if (actorNum == -1)
		{
			return;
		}

		// Store the actor in the map
		_convMap[num].actors.emplace(actorNum, value);
	}
	else if (convSubString.substr(0, 4) == "cmd_") 
	{
		// This is a conversation command
		std::smatch cmdResults;

		if (!std::regex_match(convSubString, cmdResults, _regexConvCmd))
		{
			return; // not matching
		}

		int cmdIndex = string::convert<int>(cmdResults[1].str());
		std::string cmdSubStr = cmdResults[2];

		ConversationCommandPtr command;
		auto found = _convMap[num].commands.find(cmdIndex);

		if (found != _convMap[num].commands.end())
		{
			// Command already exists
			command = found->second;
		}
		else 
		{
			// Command with the given index does not exist yet, create it
			command = std::make_shared<ConversationCommand>();

			// Insert this into the map
			_convMap[num].commands[cmdIndex] = command;
		}

		if (cmdSubStr == "type")
		{
			try 
			{
				command->type = ConversationCommandLibrary::Instance().findCommandInfo(value).id;
			}
			catch (std::runtime_error& e) 
			{
				rError() << e.what() << std::endl;
				return;
			}
		}
		else if (cmdSubStr == "actor") 
		{
			command->actor = string::convert<int>(value);
		}
		else if (cmdSubStr == "wait_until_finished")
		{
			command->waitUntilFinished = (value == "1");
		}
		else if (cmdSubStr.substr(0,4) == "arg_") 
		{
			int cmdArgIndex = string::convert<int>(cmdSubStr.substr(4));

			command->arguments[cmdArgIndex] = value;
		}
	}
}

} // namespace conversation