-
Notifications
You must be signed in to change notification settings - Fork 172
/
factionInfo.cpp
192 lines (174 loc) · 8.08 KB
/
factionInfo.cpp
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include "factionInfo.h"
#include "scriptInterface.h"
#include "multiplayer_server.h"
/// A FactionInfo object contains presentation details and faction relationships for member SpaceObjects.
/// EmptyEpsilon has a hardcoded limit of 32 factions.
///
/// SpaceObjects belong to a faction that determines which objects are friendly, neutral, or hostile toward them.
/// For example, these relationships determine whether a SpaceObject can be targeted by weapons, docked with, or receive comms from another SpaceObject.
/// If a faction doesn't have a relationship with another faction, it treats those factions as neutral.
/// Friendly and hostile faction relationships are automatically reciprocated when set with setEnemy() and setFriendly().
///
/// If this faction consideres another faction to be hostile, it can target and fire weapons at it, and CpuShips with certain orders might pursue it.
/// If neutral, this faction can't target and fire weapons at the other faction, and other factions can dock with its stations or dockable ships.
/// If friendly, this faction acts as neutral but also shares short-range radar with PlayerSpaceships in Relay, and can grant reputation points to PlayerSpaceships of the same faction.
///
/// Many scenario and comms scripts also give friendly factions benefits at a reputation cost that netural factions do not.
/// Factions are loaded from resources/factionInfo.lua upon launching a scenario, and accessed by using the getFactionInfo() global function.
///
/// Example:
/// human_navy = getFactionInfo("Human Navy")
/// exuari = getFactionInfo("Exuari")
/// faction = FactionInfo():setName("USN"):setLocaleName(_("USN")) -- sets the internal and translatable faction names
/// faction:setGMColor(255,128,255) -- uses purple icons for this faction's SpaceObjects in GM and Spectator views
/// faction:setFriendly(human_navy):setEnemy(exuari) -- sets this faction's friendly and hostile relationships
/// faction:setDescription(_("The United Stellar Navy, or USN...")) -- sets a translatable description for this faction
REGISTER_SCRIPT_CLASS(FactionInfo)
{
/// Sets this faction's internal string name, used to reference this faction regardless of EmptyEpsilon's language setting.
/// If no locale name is defined, this sets the locale name to the same value.
/// Example: faction:setName("USN")
REGISTER_SCRIPT_CLASS_FUNCTION(FactionInfo, setName);
/// Sets this faction's name as presented in the user interface.
/// Wrap the string in the _() function to make it available for translation.
/// Example: faction:setLocaleName(_("USN"))
REGISTER_SCRIPT_CLASS_FUNCTION(FactionInfo, setLocaleName);
/// Sets the RGB color used for SpaceObjects of this faction as seen on the GM and Spectator views.
/// Defaults to white (255,255,255).
/// Example: faction:setGMColor(255,0,0) -- sets the color to red
REGISTER_SCRIPT_CLASS_FUNCTION(FactionInfo, setGMColor);
/// Sets this faction's longform description as shown in its Factions ScienceDatabase child entry.
/// Wrap the string in the _() function to make it available for translation.
/// Example: faction:setDescription(_("The United Stellar Navy, or USN...")) -- sets a translatable description for this faction
REGISTER_SCRIPT_CLASS_FUNCTION(FactionInfo, setDescription);
/// Sets the given faction to appear as hostile to SpaceObjects of this faction.
/// For example, Spaceships of this faction can target and fire at SpaceShips of the given faction.
/// Defaults to no hostile factions.
/// Warning: A faction can be designated as hostile to itself, but the behavior is not well-defined.
/// Example: faction:setEnemy(exuari) -- sets the Exuari to appear as hostile to this faction
REGISTER_SCRIPT_CLASS_FUNCTION(FactionInfo, setEnemy);
/// Sets the given faction to appear as friendly to SpaceObjects of this faction.
/// For example, PlayerSpaceships of this faction can gain reputation with it.
/// Defaults to no friendly factions.
/// Example: faction:setFriendly(exuari) -- sets the Human Navy to appear as friendly to this faction
REGISTER_SCRIPT_CLASS_FUNCTION(FactionInfo, setFriendly);
/// Sets the given faction to appear as neutral to SpaceObjects of this faction.
/// This removes any existing faction relationships between the two factions.
/// Example: faction:setNeutral(human_navy) -- sets the Human Navy to appear as neutral to this faction
REGISTER_SCRIPT_CLASS_FUNCTION(FactionInfo, setNeutral);
}
std::array<P<FactionInfo>, 32> factionInfo;
static int getFactionInfo(lua_State* L)
{
auto name = luaL_checkstring(L, 1);
for(unsigned int n = 0; n < factionInfo.size(); n++)
if (factionInfo[n] && factionInfo[n]->getName() == name)
return convert<P<FactionInfo>>::returnType(L, factionInfo[n]);
return 0;
}
/// P<FactionInfo> getFactionInfo(string faction_name)
/// Returns a reference to the FactionInfo object with the given name.
/// Use this to modify faction details and relationships with FactionInfo functions.
/// Example: faction = getFactionInfo("Human Navy") -- faction = the Human Navy FactionInfo object
REGISTER_SCRIPT_FUNCTION(getFactionInfo);
REGISTER_MULTIPLAYER_CLASS(FactionInfo, "FactionInfo");
FactionInfo::FactionInfo()
: MultiplayerObject("FactionInfo")
{
index = 255;
gm_color = {255,255,255,255};
enemy_mask = 0;
friend_mask = 0;
registerMemberReplication(&index);
registerMemberReplication(&gm_color);
registerMemberReplication(&name);
registerMemberReplication(&locale_name);
registerMemberReplication(&description);
registerMemberReplication(&enemy_mask);
registerMemberReplication(&friend_mask);
if (game_server) {
for(size_t n=0; n<factionInfo.size(); n++)
{
if (!factionInfo[n]) {
factionInfo[n] = this;
index = n;
setFriendly(this);
return;
}
}
LOG(ERROR) << "There is a limit of 32 factions.";
destroy();
}
}
FactionInfo::~FactionInfo()
{
}
void FactionInfo::update(float delta)
{
if (index != 255)
factionInfo[index] = this;
}
void FactionInfo::setEnemy(P<FactionInfo> other)
{
if (!other)
{
LOG(WARNING) << "Tried to set an undefined faction to be an enemy of " << name;
return;
}
friend_mask &=~(1U << other->index);
other->friend_mask &=~(1U << index);
enemy_mask |= (1 << other->index);
other->enemy_mask |= (1 << index);
}
void FactionInfo::setFriendly(P<FactionInfo> other)
{
if (!other)
{
LOG(WARNING) << "Tried to set an undefined faction to be friendly with " << name;
return;
}
friend_mask |= (1U << other->index);
other->friend_mask |= (1U << index);
enemy_mask &=~(1 << other->index);
other->enemy_mask &=~(1 << index);
}
void FactionInfo::setNeutral(P<FactionInfo> other)
{
if (!other)
{
LOG(WARNING) << "Tried to set an undefined faction to be neutral with " << name;
return;
}
friend_mask &=~(1 << other->index);
other->friend_mask &=~(1 << index);
enemy_mask &=~(1 << other->index);
other->enemy_mask &=~(1 << index);
}
EFactionVsFactionState FactionInfo::getState(P<FactionInfo> other)
{
if (!other) return FVF_Neutral;
if (enemy_mask & (1 << other->index)) return FVF_Enemy;
if (friend_mask & (1 << other->index)) return FVF_Friendly;
return FVF_Neutral;
}
EFactionVsFactionState FactionInfo::getState(uint8_t idx0, uint8_t idx1)
{
if (idx0 >= factionInfo.size()) return FVF_Neutral;
if (idx1 >= factionInfo.size()) return FVF_Neutral;
if (!factionInfo[idx0] || !factionInfo[idx1]) return FVF_Neutral;
return factionInfo[idx0]->getState(factionInfo[idx1]);
}
unsigned int FactionInfo::findFactionId(string name)
{
for(unsigned int n = 0; n < factionInfo.size(); n++)
if (factionInfo[n] && factionInfo[n]->name == name)
return n;
LOG(ERROR) << "Failed to find faction: " << name;
return 0;
}
void FactionInfo::reset()
{
for(unsigned int n = 0; n < factionInfo.size(); n++)
if (factionInfo[n])
factionInfo[n]->destroy();
}