Mana
Loading...
Searching...
No Matches
actorspritemanager.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "actorspritemanager.h"
23
24#include "configuration.h"
25#include "game.h"
26#include "localplayer.h"
27
28#include <algorithm>
29
31{
32 void getAutoCompleteList(std::vector<std::string>& names) const override
33 {
34 names.clear();
35
36 for (auto actor : actorSpriteManager->getAll()) {
37 if (actor->getType() != ActorSprite::PLAYER)
38 continue;
39
40 auto *being = static_cast<Being *>(actor);
41 if (!being->getName().empty())
42 names.push_back(being->getName());
43 }
44 }
45};
46
48{
49 void getAutoCompleteList(std::vector<std::string>& names) const override
50 {
51 names.clear();
52
53 for (auto actor : actorSpriteManager->getAll())
54 {
55 if (actor->getType() == ActorSprite::FLOOR_ITEM)
56 continue;
57
58 auto *being = static_cast<Being *>(actor);
59 if ((being->getType() == Being::PLAYER ||
60 being->getType() == Being::NPC) && !being->getName().empty())
61 names.push_back(being->getName());
62 }
63 }
64};
65
67{
68 mPlayerNames = std::make_unique<PlayerNamesLister>();
69 mPlayerNPCNames = std::make_unique<PlayerNPCNamesLister>();
70
72}
73
78
80{
81 mMap = map;
82
83 if (local_player)
84 local_player->setMap(map);
85}
86
88{
89 local_player = player;
90 mActors.insert(player);
91}
92
94{
95 auto *being = new Being(id, type, subtype, mMap);
96
97 mActors.insert(being);
98 return being;
99}
100
101FloorItem *ActorSpriteManager::createItem(int id, int itemId, const Vector &pos)
102{
103 auto *floorItem = new FloorItem(id, itemId, pos, mMap);
104
105 mActors.insert(floorItem);
106 return floorItem;
107}
108
110{
111 mActors.erase(actor);
112 mDeleteActors.erase(actor);
113 delete actor;
114}
115
117{
118 if (!actor || actor == local_player)
119 return;
120
121 mDeleteActors.insert(actor);
122}
123
125{
126 for (auto actor : mActors) {
127 if (actor->getId() == id && actor->getType() != ActorSprite::FLOOR_ITEM)
128 return static_cast<Being *>(actor);
129 }
130
131 return nullptr;
132}
133
135{
136 const Game *game = Game::instance();
137 if (!game)
138 return nullptr;
139
140 const int tileWidth = game->getCurrentTileWidth();
141 const int tileHeight = game->getCurrentTileHeight();
142
143 auto it = find_if(mActors.begin(), mActors.end(), [=] (ActorSprite *actor) {
144 const auto actorType = actor->getType();
145 if (actorType == ActorSprite::FLOOR_ITEM)
146 return false;
147 if (type != ActorSprite::UNKNOWN && actorType != type)
148 return false;
149
150 auto *being = static_cast<Being*>(actor);
151
152 if (!being->isTargetSelection())
153 return false;
154
155 uint16_t other_y = y + (actorType == ActorSprite::NPC ? 1 : 0);
156 const Vector &pos = being->getPosition();
157 return ((int) pos.x / tileWidth == x &&
158 ((int) pos.y / tileHeight == y
159 || (int) pos.y / tileHeight == other_y) &&
160 being->isAlive());
161 });
162
163 return it == mActors.end() ? nullptr : static_cast<Being*>(*it);
164}
165
167{
168 Map *map = Game::instance() ? Game::instance()->getCurrentMap() : nullptr;
169 if (!map)
170 return nullptr;
171
172 const int halfTileHeight = map->getTileHeight() / 2;
173
174 Being *closest = nullptr;
175 int closestDist = 0;
176
177 for (auto actor : mActors)
178 {
179 if (actor->getType() == ActorSprite::FLOOR_ITEM)
180 continue;
181
182 auto *being = static_cast<Being *>(actor);
183
184 if (!being->isTargetSelection())
185 continue;
186
187 const int halfWidth = std::max(16, being->getWidth() / 2);
188 const int height = std::max(32, being->getHeight());
189 const int halfHeight = height / 2;
190
191 // Being sprites are drawn half a tile lower than they actually stand
192 const int bottom = being->getPixelY() + halfTileHeight;
193
194 const int dist = std::max(std::abs(bottom - halfHeight - y),
195 std::abs(being->getPixelX() - x));
196
197 if ((being->isAlive() && being != local_player &&
198 being->getPixelX() - halfWidth <= x &&
199 being->getPixelX() + halfWidth >= x && bottom - height <= y &&
200 bottom >= y) &&
201 (!closest || closestDist > dist)) {
202 closest = being;
203 closestDist = dist;
204 }
205 }
206
207 return closest;
208}
209
211{
212 for (auto actor : mActors)
213 {
214 if (actor->getId() == id && actor->getType() == ActorSprite::FLOOR_ITEM)
215 return static_cast<FloorItem *>(actor);
216 }
217
218 return nullptr;
219}
220
221FloorItem *ActorSpriteManager::findItem(int x, int y, int maxDist) const
222{
223 FloorItem *item = nullptr;
224 int smallestDist = 0;
225 for (auto actor : mActors)
226 {
227 int dist = std::max(std::abs(actor->getTileX() - x),
228 std::abs(actor->getTileY() - y));
229 if ((actor->getType() == ActorSprite::FLOOR_ITEM) &&
230 ((!item && dist <= maxDist) || dist < smallestDist))
231 {
232 item = static_cast<FloorItem *>(actor);
233 smallestDist = dist;
234 }
235 }
236
237 return item;
238}
239
241 ActorSprite::Type type) const
242{
243 for (auto actor : mActors)
244 {
245 if (actor->getType() == ActorSprite::FLOOR_ITEM)
246 continue;
247
248 auto *being = static_cast<Being *>(actor);
249 if (being->getName() == name &&
250 (type == ActorSprite::UNKNOWN || type == being->getType()))
251 return being;
252 }
253 return nullptr;
254}
255
257{
258 return mActors;
259}
260
262{
263 for (auto actor : mActors)
264 actor->logic();
265
266 for (auto actor : mDeleteActors)
267 {
268 mActors.erase(actor);
269 delete actor;
270 }
271
272 mDeleteActors.clear();
273}
274
276{
277 if (local_player)
278 mActors.erase(local_player);
279
280 for (auto actor : mActors)
281 delete actor;
282 mActors.clear();
283 mDeleteActors.clear();
284
285 if (local_player)
286 mActors.insert(local_player);
287}
288
290 int maxTileDist,
292 Being *excluded) const
293{
294 Game *game = Game::instance();
295 if (!game)
296 return nullptr;
297
298 Being *closestBeing = nullptr;
299 int dist = 0;
300
301 const int maxDist = maxTileDist * game->getCurrentTileWidth();
302
303 for (auto actor : mActors)
304 {
305 if (actor->getType() == ActorSprite::FLOOR_ITEM)
306 continue;
307
308 auto *being = static_cast<Being *>(actor);
309
310 if (!being->isTargetSelection())
311 continue;
312
313 const Vector &pos = being->getPosition();
314 int d = abs(((int)pos.x) - x) + abs(((int)pos.y) - y);
315
316 if ((being->getType() == type || type == ActorSprite::UNKNOWN) &&
317 (d < dist || !closestBeing) // it is closer
318 && being->isAlive() // no dead beings
319 && being != excluded)
320 {
321 dist = d;
322 closestBeing = being;
323 }
324 }
325
326 return (maxDist >= dist) ? closestBeing : nullptr;
327}
328
330 int maxDist,
331 ActorSprite::Type type) const
332{
333 const Vector &pos = aroundBeing->getPosition();
334 return findNearestLivingBeing((int)pos.x, (int)pos.y, maxDist, type,
335 aroundBeing);
336}
337
339{
340 return mActors.find(someActor) != mActors.end();
341}
342
347
352
354{
355 for (auto actor : mActors)
356 {
357 if (actor->getType() != ActorSprite::PLAYER)
358 continue;
359
360 auto *being = static_cast<Being *>(actor);
361 if (!being->getName().empty())
362 being->updateName();
363 }
364}
365
367{
368 if (channel == Event::ConfigChannel)
369 {
370 if (event.getType() == Event::ConfigOptionChanged &&
371 event.hasValue(&Config::showGender))
372 {
374 }
375 }
376}
std::set< ActorSprite * > ActorSprites
ActorSpriteManager * actorSpriteManager
Definition game.cpp:110
Being * createBeing(int id, ActorSprite::Type type, int subtype)
Create a Being and add it to the list of ActorSprites.
AutoCompleteLister * getPlayerNPCNameLister() const
FloorItem * findItem(int id) const
Returns a specific FloorItem, by id.
Being * findNearestLivingBeing(int x, int y, int maxTileDist, ActorSprite::Type type=Being::UNKNOWN, Being *excluded=nullptr) const
Returns a being nearest to specific coordinates.
void scheduleDelete(ActorSprite *actor)
Destroys the given ActorSprite at the end of ActorSpriteManager::logic.
std::unique_ptr< AutoCompleteLister > mPlayerNPCNames
Being * findBeingByName(const std::string &name, ActorSprite::Type type=Being::UNKNOWN) const
Finds a being by name and (optionally) by type.
void destroyActor(ActorSprite *actor)
Immediately destroys the given actor.
void setPlayer(LocalPlayer *player)
Sets the current player.
bool hasActorSprite(ActorSprite *someActor) const
Returns true if the given ActorSprite is in the manager's list, false otherwise.
Being * findBeingByPixel(int x, int y) const
Returns a being at the specific pixel.
const ActorSprites & getAll() const
Returns the whole list of beings.
std::unique_ptr< AutoCompleteLister > mPlayerNames
Being * findBeing(int id) const
Returns a specific Being, by id;.
void event(Event::Channel channel, const Event &event) override
void setMap(Map *map)
Sets the map on which ActorSprites are created.
FloorItem * createItem(int id, int itemId, const Vector &position)
Create a FloorItem and add it to the list of ActorSprites.
void clear()
Destroys all ActorSprites except the local player.
void logic()
Performs ActorSprite logic and deletes ActorSprite scheduled to be deleted.
AutoCompleteLister * getPlayerNameLister() const
int getPixelX() const
Returns the pixels X coordinate of the actor.
Definition actor.h:65
const Vector & getPosition() const
Returns the pixel position of this actor.
Definition actor.h:53
Definition being.h:65
void setMap(Map *map) final
Definition being.cpp:1398
void updateName()
Definition being.cpp:1029
void logic() override
Performs being logic.
Definition being.cpp:810
void listen(Event::Channel channel)
Definition event.h:42
@ ConfigOptionChanged
Definition event.h:68
Channel
Definition event.h:45
@ ConfigChannel
Definition event.h:51
An item lying on the floor.
Definition flooritem.h:32
The main class responsible for running the game.
Definition game.h:37
int getCurrentTileWidth() const
Convenience functions used to get the current tile width and height.
Definition game.cpp:917
Map * getCurrentMap()
Returns the currently active map.
Definition game.h:70
int getCurrentTileHeight() const
Definition game.cpp:925
static Game * instance()
Provides access to the game instance.
Definition game.h:53
The local player character.
Definition localplayer.h:75
A tile map.
Definition map.h:147
int getTileHeight() const
Returns the tile height used by this map.
Definition map.h:271
void getAutoCompleteList(std::vector< std::string > &names) const override
void getAutoCompleteList(std::vector< std::string > &names) const override
Vector class.
Definition vector.h:33
float y
Definition vector.h:172
float x
Definition vector.h:171
LocalPlayer * local_player
bool showGender