-
Notifications
You must be signed in to change notification settings - Fork 1
/
Raven_Teammate.cpp
235 lines (197 loc) · 5.4 KB
/
Raven_Teammate.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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#include "Raven_Teammate.h"
#include "lua/Raven_Scriptor.h"
#include "Raven_SensoryMemory.h"
#include "time/Regulator.h"
#include "Messaging/Telegram.h"
#include "Raven_Messages.h"
#include "Messaging/MessageDispatcher.h"
#include "goals/Raven_Goal_Types.h"
#include "Goal_ThinkAsTeammate.h"
#include "Debug\DebugConsole.h"
#include "Raven_TeammateSteeringBehaviors.h"
#include "Raven_TeamManager.h"
#include "Raven_Leader.h"
#include "Game\EntityManager.h"
#include "Raven_TeammateSensoryMemory.h"
#include <limits>
Raven_Teammate::Raven_Teammate(Raven_Game* world, Vector2D pos, Raven_TeamManager* teammanager)
: Raven_Teammate(world, pos, teammanager, new Goal_ThinkAsTeammate(this))
{
}
Raven_Teammate::Raven_Teammate(Raven_Game * world, Vector2D pos, Raven_TeamManager * teammanager, Goal_Think * goal)
: Raven_Bot(world, pos, new Raven_TeammateSteering(world, this), goal, new Raven_TeammateSensoryMemory(this, script->GetDouble("Bot_MemorySpan"))),
m_pTeamManager(teammanager),
m_pPartner(nullptr),
m_savedPosition(Vector2D())
{
m_pPartnerUpdateRegulator = new Regulator(script->GetDouble("Teammate_PartnerUpdateFreq"));
}
Raven_Teammate::~Raven_Teammate()
{
}
void Raven_Teammate::Update()
{
Raven_Bot::Update();
if (isPossessed()) {
m_pPartner = nullptr;
}
else {
if (TeamSize() == 1) {
m_pPartner = nullptr;
}
else if (m_pPartner && m_pPartner->isDead()) {
m_pPartner = nullptr;
}
if (m_pPartnerUpdateRegulator->isReady()) {
UpdatePartner();
}
}
}
bool Raven_Teammate::HandleMessage(const Telegram& msg)
{
//first see if the current goal accepts the message
if (GetBrain()->HandleMessage(msg)) return true;
Raven_Bot * sender = nullptr;
// Treat Raven_Teammate specific message
switch (msg.Msg)
{
case Msg_TakeThatMF:
{
#ifdef FRIENDLY_FIRE //Teammates can do damage to each other
//just return if already dead or spawning
if (isDead() || isSpawning()) return true;
//the extra info field of the telegram carries the amount of damage
ReduceHealth(DereferenceToType<int>(msg.ExtraInfo));
//if this bot is now dead let the shooter know
if (isDead())
{
Dispatcher->DispatchMsg(SEND_MSG_IMMEDIATELY,
ID(),
msg.Sender,
Msg_YouGotMeYouSOB,
NO_ADDITIONAL_INFO);
}
#else
sender = static_cast<Raven_Bot*>(EntityMgr->GetEntityFromID(msg.Sender));
if (!m_pTeamManager->isTeammate(sender)) {
//just return if already dead or spawning
if (isDead() || isSpawning()) return true;
//the extra info field of the telegram carries the amount of damage
ReduceHealth(DereferenceToType<int>(msg.ExtraInfo));
//if this bot is now dead let the shooter know
if (isDead())
{
Dispatcher->DispatchMsg(SEND_MSG_IMMEDIATELY,
ID(),
msg.Sender,
Msg_YouGotMeYouSOB,
NO_ADDITIONAL_INFO);
}
}
#endif
return true;
}
case Msg_YouGotMeYouSOB:
{
sender = static_cast<Raven_Bot*>(EntityMgr->GetEntityFromID(msg.Sender));
if (!sender->HasTag(teammate_bot) || !m_pTeamManager->isTeammate(sender)) {
IncrementScore();
if (GetTargetBot() && GetTargetBot()->ID() == msg.Sender) {
//the bot this bot has just killed should be removed as the target
m_pTargSys->ClearTarget();
}
}
return true;
}
case Msg_GunshotSound:
{
sender = static_cast<Raven_Bot*>(msg.ExtraInfo);
if (!m_pTeamManager->isTeammate(sender)) {
//add the source of this sound to the bot's percepts
GetSensoryMem()->UpdateWithSoundSource((Raven_Bot*)msg.ExtraInfo);
}
return true;
}
case Msg_UserHasRemovedBot:
{
Raven_Bot* pRemovedBot = (Raven_Bot*)msg.ExtraInfo;
GetSensoryMem()->RemoveBotFromMemory(pRemovedBot);
//if the removed bot is the target, make sure the target is cleared
if (pRemovedBot == GetTargetSys()->GetTarget())
{
GetTargetSys()->ClearTarget();
}
if (pRemovedBot == m_pPartner) {
m_pPartner = NULL;
}
return true;
}
case Msg_AskForLocation:
{
m_savedPosition = Pos();
Dispatcher->DispatchMsg(SEND_MSG_IMMEDIATELY,
ID(),
msg.Sender,
Msg_TeammateLocation,
static_cast<void *>(&m_savedPosition)
);
return true;
}
case Msg_TeammateLocation:
{
if (msg.ExtraInfo)
{
Raven_Teammate * sender = static_cast<Raven_Teammate*>(EntityMgr->GetEntityFromID(msg.Sender));
if (!m_pPartner || m_pPartner->isDead()) {
m_pPartner = sender;
}
else {
Vector2D senderPos = *static_cast<Vector2D *>(msg.ExtraInfo);
double distToPartner = Pos().Distance(m_pPartner->Pos());
if (distToPartner > Pos().Distance(senderPos)) {
m_pPartner = sender;
}
}
}
return true;
}
default:
return false;
}
}
void Raven_Teammate::UpdatePartner()
{
// ask to all teammates their location
m_pTeamManager->SendMessageToAllTeammates(this, SEND_MSG_IMMEDIATELY, Msg_AskForLocation);
}
bool Raven_Teammate::HasPartner()
{
return m_pPartner != nullptr && !m_pPartner->isDead();
}
double Raven_Teammate::DistanceToPartner()
{
if (m_pPartner && !m_pPartner->isDead() && !isDead()) {
return Pos().Distance(m_pPartner->Pos());
}
return DBL_MAX;
}
Goal_ThinkAsTeammate * const Raven_Teammate::GetBrain()
{
return static_cast<Goal_ThinkAsTeammate *>(m_pBrain);
}
Raven_TeamManager * Raven_Teammate::GetTeam() const
{
return m_pTeamManager;
}
bool Raven_Teammate::HasLeader() const
{
return m_pTeamManager->HasLeader();
}
int Raven_Teammate::TeamSize()
{
return m_pTeamManager->TeamSize();
}
bool Raven_Teammate::HasTag(int tag) const
{
return Raven_Bot::HasTag(tag) || tag == teammate_bot;
}