Client Upload Part 2

RD Core / Commit #5

Commit Client Upload Part 2

Alex Alex committed 19/10/2026 00:06 main Patch
1,244 files +271,215 -0
A RD_Client/src/client/container.cpp +143-0 View file
@@ -0,0 +1,143 @@
1+/*
2+ * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#include "container.h"
24+#include "item.h"
25+
26+Container::Container(int id, int capacity, const std::string& name, const ItemPtr& containerItem, bool hasParent, bool isUnlocked, bool hasPages, int containerSize, int firstIndex)
27+{
28+ m_id = id;
29+ m_capacity = capacity;
30+ m_name = name;
31+ m_containerItem = containerItem;
32+ m_hasParent = hasParent;
33+ m_closed = false;
34+ m_unlocked = isUnlocked;
35+ m_hasPages = hasPages;
36+ m_size = containerSize;
37+ m_firstIndex = firstIndex;
38+}
39+
40+ItemPtr Container::getItem(int slot)
41+{
42+ if(slot < 0 || slot >= (int)m_items.size())
43+ return nullptr;
44+ return m_items[slot];
45+}
46+
47+void Container::onOpen(const ContainerPtr& previousContainer)
48+{
49+ callLuaField("onOpen", previousContainer);
50+}
51+
52+void Container::onClose()
53+{
54+ m_closed = true;
55+ callLuaField("onClose");
56+}
57+
58+void Container::onAddItem(const ItemPtr& item, int slot)
59+{
60+ slot -= m_firstIndex;
61+
62+ m_size++;
63+ // indicates that there is a new item on next page
64+ if(m_hasPages && slot > m_capacity) {
65+ callLuaField("onSizeChange", m_size);
66+ return;
67+ }
68+
69+ if(slot == 0)
70+ m_items.push_front(item);
71+ else
72+ m_items.push_back(item);
73+ updateItemsPositions();
74+
75+ callLuaField("onSizeChange", m_size);
76+ callLuaField("onAddItem", slot, item);
77+}
78+
79+ItemPtr Container::findItemById(uint itemId, int subType)
80+{
81+ for(const ItemPtr& item : m_items)
82+ if(item->getId() == itemId && (subType == -1 || item->getSubType() == subType))
83+ return item;
84+ return nullptr;
85+}
86+
87+void Container::onAddItems(const std::vector<ItemPtr>& items)
88+{
89+ for(const ItemPtr& item : items)
90+ m_items.push_back(item);
91+ updateItemsPositions();
92+}
93+
94+void Container::onUpdateItem(int slot, const ItemPtr& item)
95+{
96+ slot -= m_firstIndex;
97+ if(slot < 0 || slot >= (int)m_items.size()) {
98+ g_logger.traceError("slot not found");
99+ return;
100+ }
101+
102+ ItemPtr oldItem = m_items[slot];
103+ m_items[slot] = item;
104+ item->setPosition(getSlotPosition(slot));
105+
106+ callLuaField("onUpdateItem", slot, item, oldItem);
107+}
108+
109+void Container::onRemoveItem(int slot, const ItemPtr& lastItem)
110+{
111+ slot -= m_firstIndex;
112+ if(m_hasPages && slot >= (int)m_items.size()) {
113+ m_size--;
114+ callLuaField("onSizeChange", m_size);
115+ return;
116+ }
117+
118+ if(slot < 0 || slot >= (int)m_items.size()) {
119+ g_logger.traceError("slot not found");
120+ return;
121+ }
122+
123+ ItemPtr item = m_items[slot];
124+ m_items.erase(m_items.begin() + slot);
125+
126+
127+ if(lastItem) {
128+ onAddItem(lastItem, m_firstIndex + m_capacity - 1);
129+ m_size--;
130+ }
131+ m_size--;
132+
133+ updateItemsPositions();
134+
135+ callLuaField("onSizeChange", m_size);
136+ callLuaField("onRemoveItem", slot, item);
137+}
138+
139+void Container::updateItemsPositions()
140+{
141+ for(int slot = 0; slot < (int)m_items.size(); ++slot)
142+ m_items[slot]->setPosition(getSlotPosition(slot));
143+}
A RD_Client/src/client/container.h +80-0 View file
@@ -0,0 +1,80 @@
1+/*
2+ * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#ifndef CONTAINER_H
24+#define CONTAINER_H
25+
26+#include "declarations.h"
27+#include "item.h"
28+
29+#include <framework/luaengine/luaobject.h>
30+
31+// @bindclass
32+class Container : public LuaObject
33+{
34+protected:
35+ Container(int id, int capacity, const std::string& name, const ItemPtr& containerItem, bool hasParent, bool isUnlocked, bool hasPages, int containerSize, int firstIndex);
36+
37+public:
38+ ItemPtr getItem(int slot);
39+ std::deque<ItemPtr> getItems() { return m_items; }
40+ int getItemsCount() { return m_items.size(); }
41+ Position getSlotPosition(int slot) { return Position(0xffff, m_id | 0x40, slot); }
42+ int getId() { return m_id; }
43+ int getCapacity() { return m_capacity; }
44+ ItemPtr getContainerItem() { return m_containerItem; }
45+ std::string getName() { return m_name; }
46+ bool hasParent() { return m_hasParent; }
47+ bool isClosed() { return m_closed; }
48+ bool isUnlocked() { return m_unlocked; }
49+ bool hasPages() { return m_hasPages; }
50+ int getSize() { return m_size; }
51+ int getFirstIndex() { return m_firstIndex; }
52+ ItemPtr findItemById(uint itemId, int subType);
53+
54+protected:
55+ void onOpen(const ContainerPtr& previousContainer);
56+ void onClose();
57+ void onAddItem(const ItemPtr& item, int slot);
58+ void onAddItems(const std::vector<ItemPtr>& items);
59+ void onUpdateItem(int slot, const ItemPtr& item);
60+ void onRemoveItem(int slot, const ItemPtr& lastItem);
61+
62+ friend class Game;
63+
64+private:
65+ void updateItemsPositions();
66+
67+ int m_id;
68+ int m_capacity;
69+ ItemPtr m_containerItem;
70+ std::string m_name;
71+ bool m_hasParent;
72+ bool m_closed;
73+ bool m_unlocked;
74+ bool m_hasPages;
75+ int m_size;
76+ int m_firstIndex;
77+ std::deque<ItemPtr> m_items;
78+};
79+
80+#endif
A RD_Client/src/client/creature.h +320-0 View file
@@ -0,0 +1,320 @@
1+/*
2+ * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#ifndef CREATURE_H
24+#define CREATURE_H
25+
26+#include "thing.h"
27+#include "outfit.h"
28+#include "tile.h"
29+#include "mapview.h"
30+#include <framework/core/scheduledevent.h>
31+#include <framework/core/declarations.h>
32+#include <framework/core/timer.h>
33+#include <framework/graphics/fontmanager.h>
34+#include <framework/graphics/cachedtext.h>
35+#include <framework/ui/uiwidget.h>
36+
37+ // @bindclass
38+class Creature : public Thing
39+{
40+public:
41+ enum {
42+ SHIELD_BLINK_TICKS = 500,
43+ VOLATILE_SQUARE_DURATION = 1000
44+ };
45+
46+ Creature();
47+ virtual ~Creature();
48+
49+ virtual void draw(const Point& dest, bool animate = true, LightView* lightView = nullptr);
50+ virtual void drawOutfit(const Rect& destRect, Otc::Direction direction = Otc::InvalidDirection, const Color& color = Color::white, bool animate = false, bool ui = false, bool oldScaling = false);
51+
52+ void drawInformation(const Point& point, bool useGray, const Rect& parentRect, int drawFlags);
53+
54+ bool isInsideOffset(Point offset);
55+
56+ void setId(uint32 id) { m_id = id; }
57+ void setName(const std::string& name);
58+ void setManaPercent(int8 value) { m_manaPercent = value; }
59+ void setHealthPercent(uint8 healthPercent);
60+ void setDirection(Otc::Direction direction);
61+ void setOutfit(const Outfit& outfit);
62+ void attackPulse(const Outfit& outfit, uint16 duration);
63+ void setOutfitColor(const Color& color, int duration);
64+ void setLight(const Light& light) { m_light = light; }
65+ void setSpeed(uint16 speed);
66+ void setBaseSpeed(double baseSpeed);
67+ void setSkull(uint8 skull);
68+ void setShield(uint8 shield);
69+ void setEmblem(uint8 emblem);
70+ void setType(uint8 type);
71+ void setIcon(uint8 icon);
72+ void setSkullTexture(const std::string& filename);
73+ void setShieldTexture(const std::string& filename, bool blink);
74+ void setEmblemTexture(const std::string& filename);
75+ void setTypeTexture(const std::string& filename);
76+ void setIconTexture(const std::string& filename);
77+ void setPassable(bool passable) { m_passable = passable; }
78+ void setSpeedFormula(double speedA, double speedB, double speedC);
79+
80+ void addTimedSquare(uint8 color);
81+ void removeTimedSquare() { m_showTimedSquare = false; }
82+
83+ void showStaticSquare(const Color& color) { m_showStaticSquare = true; m_staticSquareColor = color; }
84+ void hideStaticSquare() { m_showStaticSquare = false; }
85+
86+ void setInformationColor(const Color& color) { m_useCustomInformationColor = true; m_informationColor = color; }
87+ void resetInformationColor() { m_useCustomInformationColor = false; setHealthPercent(getHealthPercent()); }
88+
89+ Point getInformationOffset() { return m_informationOffset; }
90+ void setInformationOffset(int x, int y) { m_informationOffset = Point(x, y); }
91+
92+ void setText(const std::string& text, const Color& color);
93+ std::string getText();
94+ void clearText() { setText("", Color::white); }
95+
96+ void setTitle(const std::string& title, const std::string& font, const Color& color);
97+ void clearTitle() { setTitle("", "", Color::white); }
98+ std::string getTitle() { return m_titleCache.getText(); }
99+
100+ uint32 getId() { return m_id; }
101+ std::string getName() { return m_name; }
102+ Point getWingsOffset() { return m_wingsOffset; }
103+ void setWingsOffset(int x, int y) {
104+ m_wingsOffset.x = x;
105+ m_wingsOffset.y = y;
106+ }
107+ uint8 getHealthPercent() { return m_healthPercent; }
108+ int8 getManaPercent() { return m_manaPercent; }
109+ Otc::Direction getDirection() { return m_direction; }
110+ Otc::Direction getWalkDirection() { return m_walkDirection; }
111+ Outfit getOutfit() { return m_outfit; }
112+ int getWings() { return m_outfit.getWings(); }
113+ Light getLight() { return m_light; }
114+ uint16 getSpeed() { return m_speed; }
115+ double getBaseSpeed() { return m_baseSpeed; }
116+ uint8 getSkull() { return m_skull; }
117+ uint8 getShield() { return m_shield; }
118+ uint8 getEmblem() { return m_emblem; }
119+ uint8 getType() { return m_type; }
120+ uint8 getIcon() { return m_icon; }
121+ bool isPassable() { return m_passable; }
122+ Point getDrawOffset();
123+ uint16 getStepDuration(bool ignoreDiagonal = false, Otc::Direction dir = Otc::InvalidDirection);
124+ Point getWalkOffset(bool inNextFrame = false) { return inNextFrame ? m_walkOffsetInNextFrame : m_walkOffset; }
125+ Position getLastStepFromPosition() { return m_lastStepFromPosition; }
126+ Position getLastStepToPosition() { return m_lastStepToPosition; }
127+ float getStepProgress() { return m_walkTimer.ticksElapsed() / getStepDuration(); }
128+ int getStepTicksLeft() { return getStepDuration() - m_walkTimer.ticksElapsed(); }
129+ ticks_t getWalkTicksElapsed() { return m_walkTimer.ticksElapsed(); }
130+ double getSpeedFormula(Otc::SpeedFormula formula) { return m_speedFormula[formula]; }
131+ bool hasSpeedFormula();
132+ std::array<double, Otc::LastSpeedFormula> getSpeedFormulaArray() { return m_speedFormula; }
133+ virtual Point getDisplacement();
134+ virtual int getDisplacementX();
135+ virtual int getDisplacementY();
136+ virtual int getExactSize(int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animationPhase = 0);
137+ PointF getJumpOffset() { return m_jumpOffset; }
138+ bool isTimedSquareVisible() { return m_showTimedSquare; }
139+ Color getTimedSquareColor() { return m_timedSquareColor; }
140+ bool isStaticSquareVisible() { return m_showStaticSquare; }
141+ Color getStaticSquareColor() { return m_staticSquareColor; }
142+
143+ void updateShield();
144+
145+ // walk related
146+ int getWalkAnimationPhases();
147+ virtual void turn(Otc::Direction direction);
148+ void jump(int height, int duration);
149+ virtual void walk(const Position& oldPos, const Position& newPos);
150+ virtual void stopWalk();
151+ void allowAppearWalk(uint16_t stepSpeed) { m_allowAppearWalk = true; m_stepDuration = stepSpeed; }
152+
153+ bool isWalking() { return m_walking; }
154+ bool isRemoved() { return m_removed; }
155+ bool isInvisible() { return m_outfit.getCategory() == ThingCategoryEffect && m_outfit.getAuxId() == 13; }
156+ bool isDead() { return m_healthPercent <= 0; }
157+ bool canBeSeen() { return !isInvisible() || isPlayer(); }
158+
159+ bool isCreature() { return true; }
160+ bool canShoot(int distance);
161+
162+ const ThingTypePtr& getThingType();
163+ ThingType *rawGetThingType();
164+
165+ virtual void onPositionChange(const Position& newPos, const Position& oldPos);
166+ virtual void onAppear();
167+ virtual void onDisappear();
168+ virtual void onDeath();
169+
170+ virtual bool isPreWalking() { return false; }
171+ virtual Position getPrewalkingPosition(bool beforePrewalk = false) { return m_position; }
172+
173+ TilePtr getWalkingTileOrTile() {
174+ return m_walkingTile ? m_walkingTile : getTile();
175+ }
176+
177+ virtual bool isServerWalking() { return true; }
178+
179+ void setElevation(uint8 elevation) {
180+ m_elevation = elevation;
181+ }
182+ uint8 getElevation() {
183+ return m_elevation;
184+ }
185+
186+ // widgets
187+ void addTopWidget(const UIWidgetPtr& widget);
188+ void addBottomWidget(const UIWidgetPtr& widget);
189+ void addDirectionalWidget(const UIWidgetPtr& widget);
190+ void removeTopWidget(const UIWidgetPtr& widget);
191+ void removeBottomWidget(const UIWidgetPtr& widget);
192+ void removeDirectionalWidget(const UIWidgetPtr& widget);
193+ std::list<UIWidgetPtr> getTopWidgets();
194+ std::list<UIWidgetPtr> getBottomWidgets();
195+ std::list<UIWidgetPtr> getDirectionalWdigets();
196+ void clearWidgets();
197+ void clearTopWidgets();
198+ void clearBottomWidgets();
199+ void clearDirectionalWidgets();
200+ void drawTopWidgets(const Point& rect, const Otc::Direction direction);
201+ void drawBottomWidgets(const Point& rect, const Otc::Direction direction);
202+
203+ // progress bar
204+ uint8 getProgressBarPercent() { return m_progressBarPercent; }
205+ void setProgressBar(uint32 duration, bool ltr);
206+ void updateProgressBar(uint32 duration, bool ltr);
207+
208+protected:
209+ virtual void updateWalkAnimation(uint8 totalPixelsWalked);
210+ virtual void updateWalkOffset(uint8 totalPixelsWalked, bool inNextFrame = false);
211+ void updateWalkingTile();
212+ virtual void nextWalkUpdate();
213+ virtual void updateWalk();
214+ virtual void terminateWalk();
215+
216+ void updateOutfitColor(Color color, Color finalColor, Color delta, int duration);
217+ void updateJump();
218+
219+ uint32 m_id;
220+ std::string m_name;
221+ uint8 m_healthPercent;
222+ int8 m_manaPercent;
223+ Otc::Direction m_direction;
224+ Otc::Direction m_walkDirection;
225+ Outfit m_outfit;
226+ Light m_light;
227+ uint16 m_speed;
228+ double m_baseSpeed;
229+ uint8 m_skull;
230+ uint8 m_shield;
231+ uint8 m_emblem;
232+ uint8 m_type;
233+ uint8 m_icon;
234+ TexturePtr m_skullTexture;
235+ TexturePtr m_shieldTexture;
236+ TexturePtr m_emblemTexture;
237+ TexturePtr m_typeTexture;
238+ TexturePtr m_iconTexture;
239+ stdext::boolean<true> m_showShieldTexture;
240+ stdext::boolean<false> m_shieldBlink;
241+ stdext::boolean<false> m_passable;
242+ Color m_timedSquareColor;
243+ Color m_staticSquareColor;
244+ Color m_nameColor;
245+ stdext::boolean<false> m_showTimedSquare;
246+ stdext::boolean<false> m_showStaticSquare;
247+ stdext::boolean<true> m_removed;
248+ CachedText m_nameCache;
249+ Color m_informationColor;
250+ bool m_useCustomInformationColor = false;
251+ Point m_informationOffset;
252+ Point m_wingsOffset;
253+ Color m_outfitColor;
254+ ScheduledEventPtr m_outfitColorUpdateEvent;
255+ Timer m_outfitColorTimer;
256+ CachedText m_titleCache;
257+ Color m_titleColor;
258+
259+ static std::array<double, Otc::LastSpeedFormula> m_speedFormula;
260+
261+ // walk related
262+ int m_walkAnimationPhase;
263+ uint8 m_walkedPixels;
264+ uint m_footStep;
265+ Timer m_walkTimer;
266+ ticks_t m_footLastStep;
267+ TilePtr m_walkingTile;
268+ stdext::boolean<false> m_walking;
269+ stdext::boolean<false> m_allowAppearWalk;
270+ ScheduledEventPtr m_walkUpdateEvent;
271+ ScheduledEventPtr m_walkFinishAnimEvent;
272+ EventPtr m_disappearEvent;
273+ Point m_walkOffset;
274+ Point m_walkOffsetInNextFrame;
275+ Otc::Direction m_lastStepDirection;
276+ Position m_lastStepFromPosition;
277+ Position m_lastStepToPosition;
278+ Position m_oldPosition;
279+ uint8 m_elevation = 0;
280+ uint16 m_stepDuration = 0;
281+
282+ Timer m_attackPulseTimer;
283+ uint16 m_attackPulseDuration = 0;
284+ uint getAttackPulsePhase();
285+
286+ // jump related
287+ float m_jumpHeight = 0;
288+ float m_jumpDuration = 0;
289+ PointF m_jumpOffset;
290+ Timer m_jumpTimer;
291+
292+ // for bot
293+ StaticTextPtr m_text;
294+
295+ // widgets
296+ std::list<UIWidgetPtr> m_bottomWidgets;
297+ std::list<UIWidgetPtr> m_directionalWidgets;
298+ std::list<UIWidgetPtr> m_topWidgets;
299+
300+ // progress bar
301+ uint8 m_progressBarPercent;
302+ ScheduledEventPtr m_progressBarUpdateEvent;
303+ Timer m_progressBarTimer;
304+};
305+
306+// @bindclass
307+class Npc : public Creature
308+{
309+public:
310+ bool isNpc() { return true; }
311+};
312+
313+// @bindclass
314+class Monster : public Creature
315+{
316+public:
317+ bool isMonster() { return true; }
318+};
319+
320+#endif
A RD_Client/src/client/creatures.cpp +426-0 View file
@@ -0,0 +1,426 @@
1+/*
2+ * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#include "creatures.h"
24+#include "creature.h"
25+#include "map.h"
26+
27+#include <framework/xml/tinyxml.h>
28+#include <framework/core/resourcemanager.h>
29+
30+CreatureManager g_creatures;
31+
32+static bool isInZone(const Position& pos/* placePos*/,
33+ const Position& centerPos,
34+ int radius)
35+{
36+ if(radius == -1)
37+ return true;
38+ return ((pos.x >= centerPos.x - radius) && (pos.x <= centerPos.x + radius) &&
39+ (pos.y >= centerPos.y - radius) && (pos.y <= centerPos.y + radius)
40+ );
41+}
42+
43+void CreatureManager::terminate()
44+{
45+ clearSpawns();
46+ clear();
47+ m_nullCreature = nullptr;
48+}
49+
50+void Spawn::load(TiXmlElement* node)
51+{
52+ Position centerPos;
53+ centerPos.x = node->readType<int>("centerx");
54+ centerPos.y = node->readType<int>("centery");
55+ centerPos.z = node->readType<int>("centerz");
56+
57+ setCenterPos(centerPos);
58+ setRadius(node->readType<int32>("radius"));
59+
60+ CreatureTypePtr cType(nullptr);
61+ for(TiXmlElement* cNode = node->FirstChildElement(); cNode; cNode = cNode->NextSiblingElement()) {
62+ if(cNode->ValueStr() != "monster" && cNode->ValueStr() != "npc")
63+ stdext::throw_exception(stdext::format("invalid spawn-subnode %s", cNode->ValueStr()));
64+
65+ std::string cName = cNode->Attribute("name");
66+ stdext::tolower(cName);
67+ stdext::trim(cName);
68+ stdext::ucwords(cName);
69+
70+ if (!(cType = g_creatures.getCreatureByName(cName)))
71+ continue;
72+
73+ cType->setSpawnTime(cNode->readType<int>("spawntime"));
74+ Otc::Direction dir = Otc::North;
75+ int16 dir_ = cNode->readType<int16>("direction");
76+ if(dir_ >= Otc::East && dir_ <= Otc::West)
77+ dir = (Otc::Direction)dir_;
78+ cType->setDirection(dir);
79+
80+ Position placePos;
81+ placePos.x = centerPos.x + cNode->readType<int>("x");
82+ placePos.y = centerPos.y + cNode->readType<int>("y");
83+ placePos.z = cNode->readType<int>("z");
84+
85+ cType->setRace(cNode->ValueStr() == "npc" ? CreatureRaceNpc : CreatureRaceMonster);
86+ addCreature(placePos, cType);
87+ }
88+}
89+
90+void Spawn::save(TiXmlElement* node)
91+{
92+ const Position& c = getCenterPos();
93+ node->SetAttribute("centerx", c.x);
94+ node->SetAttribute("centery", c.y);
95+ node->SetAttribute("centerz", c.z);
96+
97+ node->SetAttribute("radius", getRadius());
98+
99+ TiXmlElement* creatureNode = nullptr;
100+
101+ for(const auto& pair : m_creatures) {
102+ const CreatureTypePtr& creature = pair.second;
103+ if(!(creatureNode = new TiXmlElement(creature->getRace() == CreatureRaceNpc ? "npc" : "monster")))
104+ stdext::throw_exception("Spawn::save: Ran out of memory while allocating XML element! Terminating now.");
105+
106+ creatureNode->SetAttribute("name", creature->getName());
107+ creatureNode->SetAttribute("spawntime", creature->getSpawnTime());
108+ creatureNode->SetAttribute("direction", creature->getDirection());
109+
110+ const Position& placePos = pair.first;
111+ VALIDATE(placePos.isValid());
112+
113+ creatureNode->SetAttribute("x", placePos.x - c.x);
114+ creatureNode->SetAttribute("y", placePos.y - c.y);
115+ creatureNode->SetAttribute("z", placePos.z);
116+
117+ node->LinkEndChild(creatureNode);
118+ }
119+}
120+
121+void Spawn::addCreature(const Position& placePos, const CreatureTypePtr& cType)
122+{
123+ const Position& centerPos = getCenterPos();
124+ int m_radius = getRadius();
125+ if(!isInZone(placePos, centerPos, m_radius)) {
126+ g_logger.warning(stdext::format("cannot place creature at %s (spawn's center position: %s, spawn radius: %d) (increment radius)",
127+ stdext::to_string(placePos), stdext::to_string(centerPos),
128+ m_radius
129+ ));
130+ return;
131+ }
132+
133+ g_map.addThing(cType->cast(), placePos, 4);
134+ m_creatures.insert(std::make_pair(placePos, cType));
135+}
136+
137+void Spawn::removeCreature(const Position& pos)
138+{
139+ auto iterator = m_creatures.find(pos);
140+ if(iterator != m_creatures.end()) {
141+ VALIDATE(iterator->first.isValid());
142+ VALIDATE(g_map.removeThingByPos(iterator->first, 4));
143+ m_creatures.erase(iterator);
144+ }
145+}
146+
147+std::vector<CreatureTypePtr> Spawn::getCreatures()
148+{
149+ std::vector<CreatureTypePtr> creatures;
150+ for (auto p : m_creatures)
151+ creatures.push_back(p.second);
152+ return creatures;
153+}
154+
155+CreaturePtr CreatureType::cast()
156+{
157+ CreaturePtr ret(new Creature);
158+
159+ std::string cName = getName();
160+ stdext::tolower(cName);
161+ stdext::trim(cName);
162+ stdext::ucwords(cName);
163+ ret->setName(cName);
164+
165+ ret->setDirection(getDirection());
166+ ret->setOutfit(getOutfit());
167+ return ret;
168+}
169+
170+CreatureManager::CreatureManager()
171+{
172+ m_nullCreature = CreatureTypePtr(new CreatureType);
173+}
174+
175+void CreatureManager::clearSpawns()
176+{
177+ for(auto pair : m_spawns)
178+ pair.second->clear();
179+ m_spawns.clear();
180+}
181+
182+void CreatureManager::loadMonsters(const std::string& file)
183+{
184+ TiXmlDocument doc;
185+ doc.Parse(g_resources.readFileContents(file).c_str());
186+ if(doc.Error())
187+ stdext::throw_exception(stdext::format("cannot open monsters file '%s': '%s'", file, doc.ErrorDesc()));
188+
189+ TiXmlElement* root = doc.FirstChildElement();
190+ if(!root || root->ValueStr() != "monsters")
191+ stdext::throw_exception("malformed monsters xml file");
192+
193+ for(TiXmlElement* monster = root->FirstChildElement(); monster; monster = monster->NextSiblingElement()) {
194+ std::string fname = file.substr(0, file.find_last_of('/')) + '/' + monster->Attribute("file");
195+ if(fname.substr(fname.length() - 4) != ".xml")
196+ fname += ".xml";
197+
198+ loadSingleCreature(fname);
199+ }
200+
201+ doc.Clear();
202+ m_loaded = true;
203+}
204+
205+void CreatureManager::loadSingleCreature(const std::string& file)
206+{
207+ loadCreatureBuffer(g_resources.readFileContents(file));
208+}
209+
210+void CreatureManager::loadNpcs(const std::string& folder)
211+{
212+ std::string tmp = folder;
213+ if(!stdext::ends_with(tmp, "/"))
214+ tmp += "/";
215+
216+ if(!g_resources.directoryExists(tmp))
217+ stdext::throw_exception(stdext::format("NPCs folder '%s' was not found.", folder));
218+
219+ const auto& fileList = g_resources.listDirectoryFiles(tmp);
220+ for(const std::string& file : fileList)
221+ loadCreatureBuffer(g_resources.readFileContents(tmp + file));
222+}
223+
224+void CreatureManager::loadSpawns(const std::string& fileName)
225+{
226+ if(!isLoaded()) {
227+ g_logger.warning("creatures aren't loaded yet to load spawns.");
228+ return;
229+ }
230+
231+ if(m_spawnLoaded) {
232+ g_logger.warning("attempt to reload spawns.");
233+ return;
234+ }
235+
236+ try {
237+ TiXmlDocument doc;
238+ doc.Parse(g_resources.readFileContents(fileName).c_str());
239+ if(doc.Error())
240+ stdext::throw_exception(stdext::format("cannot load spawns xml file '%s: '%s'", fileName, doc.ErrorDesc()));
241+
242+ TiXmlElement* root = doc.FirstChildElement();
243+ if(!root || root->ValueStr() != "spawns")
244+ stdext::throw_exception("malformed spawns file");
245+
246+ for(TiXmlElement* node = root->FirstChildElement(); node; node = node->NextSiblingElement()) {
247+ if(node->ValueTStr() != "spawn")
248+ stdext::throw_exception("invalid spawn node");
249+
250+ SpawnPtr spawn(new Spawn);
251+ spawn->load(node);
252+ m_spawns.insert(std::make_pair(spawn->getCenterPos(), spawn));
253+ }
254+ doc.Clear();
255+ m_spawnLoaded = true;
256+ } catch(std::exception& e) {
257+ g_logger.error(stdext::format("Failed to load '%s': %s", fileName, e.what()));
258+ }
259+}
260+
261+void CreatureManager::saveSpawns(const std::string& fileName)
262+{
263+ try {
264+ TiXmlDocument doc;
265+ doc.SetTabSize(2);
266+
267+ TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", "");
268+ doc.LinkEndChild(decl);
269+
270+ TiXmlElement* root = new TiXmlElement("spawns");
271+ doc.LinkEndChild(root);
272+
273+ for(auto pair : m_spawns) {
274+ TiXmlElement* elem = new TiXmlElement("spawn");
275+ pair.second->save(elem);
276+ root->LinkEndChild(elem);
277+ }
278+
279+ if(!doc.SaveFile("data"+fileName))
280+ stdext::throw_exception(stdext::format("failed to save spawns XML %s: %s", fileName, doc.ErrorDesc()));
281+ } catch(std::exception& e) {
282+ g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what()));
283+ }
284+}
285+
286+void CreatureManager::loadCreatureBuffer(const std::string& buffer)
287+{
288+ TiXmlDocument doc;
289+ doc.Parse(buffer.c_str());
290+ if(doc.Error())
291+ stdext::throw_exception(stdext::format("cannot load creature buffer: %s", doc.ErrorDesc()));
292+
293+ TiXmlElement* root = doc.FirstChildElement();
294+ if(!root || (root->ValueStr() != "monster" && root->ValueStr() != "npc"))
295+ stdext::throw_exception("invalid root tag name");
296+
297+ std::string cName = root->Attribute("name");
298+ stdext::tolower(cName);
299+ stdext::trim(cName);
300+ stdext::ucwords(cName);
301+
302+ CreatureTypePtr newType(new CreatureType(cName));
303+ for(TiXmlElement* attrib = root->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) {
304+ if(attrib->ValueStr() != "look")
305+ continue;
306+
307+ internalLoadCreatureBuffer(attrib, newType);
308+ break;
309+ }
310+
311+ doc.Clear();
312+}
313+
314+void CreatureManager::internalLoadCreatureBuffer(TiXmlElement* attrib, const CreatureTypePtr& m)
315+{
316+ if(std::find(m_creatures.begin(), m_creatures.end(), m) != m_creatures.end())
317+ return;
318+
319+ Outfit out;
320+
321+ int32 type = attrib->readType<int32>("type");
322+ if(type > 0) {
323+ out.setCategory(ThingCategoryCreature);
324+ out.setId(type);
325+ } else {
326+ out.setCategory(ThingCategoryItem);
327+ out.setAuxId(attrib->readType<int32>("typeex"));
328+ }
329+
330+ {
331+ out.setHead(attrib->readType<int>(("head")));
332+ out.setBody(attrib->readType<int>(("body")));
333+ out.setLegs(attrib->readType<int>(("legs")));
334+ out.setFeet(attrib->readType<int>(("feet")));
335+ out.setAddons(attrib->readType<int>(("addons")));
336+ out.setMount(attrib->readType<int>(("mount")));
337+ }
338+
339+ m->setOutfit(out);
340+ m_creatures.push_back(m);
341+}
342+
343+const CreatureTypePtr& CreatureManager::getCreatureByName(std::string name)
344+{
345+ stdext::tolower(name);
346+ stdext::trim(name);
347+ stdext::ucwords(name);
348+ auto it = std::find_if(m_creatures.begin(), m_creatures.end(),
349+ [=] (const CreatureTypePtr& m) -> bool { return m->getName() == name; });
350+ if(it != m_creatures.end())
351+ return *it;
352+ g_logger.warning(stdext::format("could not find creature with name: %s", name));
353+ return m_nullCreature;
354+}
355+
356+const CreatureTypePtr& CreatureManager::getCreatureByLook(int look)
357+{
358+ auto findFun = [=] (const CreatureTypePtr& c) -> bool
359+ {
360+ const Outfit& o = c->getOutfit();
361+ return o.getId() == look || o.getAuxId() == look;
362+ };
363+ auto it = std::find_if(m_creatures.begin(), m_creatures.end(), findFun);
364+ if(it != m_creatures.end())
365+ return *it;
366+ g_logger.warning(stdext::format("could not find creature with looktype: %d", look));
367+ return m_nullCreature;
368+}
369+
370+SpawnPtr CreatureManager::getSpawn(const Position& centerPos)
371+{
372+ auto it = m_spawns.find(centerPos);
373+ if(it != m_spawns.end())
374+ return it->second;
375+ g_logger.debug(stdext::format("failed to find spawn at center %s",stdext::to_string(centerPos)));
376+ return nullptr;
377+}
378+
379+SpawnPtr CreatureManager::getSpawnForPlacePos(const Position& pos)
380+{
381+ for (const auto& pair : m_spawns) {
382+ const Position& centerPos = pair.first;
383+ const SpawnPtr& spawn = pair.second;
384+
385+ if (isInZone(pos, centerPos, spawn->getRadius()))
386+ return spawn;
387+ }
388+
389+ return nullptr;
390+}
391+
392+SpawnPtr CreatureManager::addSpawn(const Position& centerPos, int radius)
393+{
394+ auto iter = m_spawns.find(centerPos);
395+ if(iter != m_spawns.end()) {
396+ if(iter->second->getRadius() != radius)
397+ iter->second->setRadius(radius);
398+ return iter->second;
399+ }
400+
401+ SpawnPtr ret(new Spawn);
402+
403+ ret->setRadius(radius);
404+ ret->setCenterPos(centerPos);
405+
406+ m_spawns.insert(std::make_pair(centerPos, ret));
407+ return ret;
408+}
409+
410+void CreatureManager::deleteSpawn(const SpawnPtr& spawn)
411+{
412+ const Position& centerPos = spawn->getCenterPos();
413+ auto it = m_spawns.find(centerPos);
414+ if(it != m_spawns.end())
415+ m_spawns.erase(it);
416+}
417+
418+std::vector<SpawnPtr> CreatureManager::getSpawns()
419+{
420+ std::vector<SpawnPtr> spawns;
421+ for (auto p : m_spawns)
422+ spawns.push_back(p.second);
423+ return spawns;
424+}
425+
426+/* vim: set ts=4 sw=4 et: */
A RD_Client/src/client/creatures.h +147-0 View file
@@ -0,0 +1,147 @@
1+/*
2+ * Copyright (c) 2010-2017 OTClient <https://github.com/edubart/otclient>
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5+ * of this software and associated documentation files (the "Software"), to deal
6+ * in the Software without restriction, including without limitation the rights
7+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+ * copies of the Software, and to permit persons to whom the Software is
9+ * furnished to do so, subject to the following conditions:
10+ *
11+ * The above copyright notice and this permission notice shall be included in
12+ * all copies or substantial portions of the Software.
13+ *
14+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+ * THE SOFTWARE.
21+ */
22+
23+#ifndef CREATURES_H
24+#define CREATURES_H
25+
26+#include "declarations.h"
27+#include <framework/luaengine/luaobject.h>
28+#include "outfit.h"
29+
30+enum CreatureAttr : uint8
31+{
32+ CreatureAttrPosition = 0,
33+ CreatureAttrName = 1,
34+ CreatureAttrOutfit = 2,
35+ CreatureAttrSpawnTime = 3,
36+ CreatureAttrDir = 4,
37+ CreatureAttrRace = 5
38+};
39+
40+enum CreatureRace : uint8
41+{
42+ CreatureRaceNpc = 0,
43+ CreatureRaceMonster = 1
44+};
45+
46+enum SpawnAttr : uint8
47+{
48+ SpawnAttrRadius = 0,
49+ SpawnAttrCenter = 1,
50+};
51+
52+class Spawn : public LuaObject
53+{
54+public:
55+ Spawn() = default;
56+ Spawn(int32 radius) { setRadius(radius); }
57+
58+ void setRadius(int32 r) { m_attribs.set(SpawnAttrRadius, r) ;}
59+ int32 getRadius() { return m_attribs.get<int32>(SpawnAttrRadius); }
60+
61+ void setCenterPos(const Position& pos) { m_attribs.set(SpawnAttrCenter, pos); }
62+ Position getCenterPos() { return m_attribs.get<Position>(SpawnAttrCenter); }
63+
64+ std::vector<CreatureTypePtr> getCreatures();
65+ void addCreature(const Position& placePos, const CreatureTypePtr& cType);
66+ void removeCreature(const Position& pos);
67+ void clear() { m_creatures.clear(); }
68+
69+protected:
70+ void load(TiXmlElement* node);
71+ void save(TiXmlElement* node);
72+
73+private:
74+ stdext::dynamic_storage<uint8> m_attribs;
75+ std::unordered_map<Position, CreatureTypePtr, PositionHasher> m_creatures;
76+ friend class CreatureManager;
77+};
78+
79+class CreatureType : public LuaObject
80+{
81+public:
82+ CreatureType() = default;
83+ CreatureType(const std::string& name) { setName(name); }
84+
85+ void setSpawnTime(int32 spawnTime) { m_attribs.set(CreatureAttrSpawnTime, spawnTime); }
86+ int32 getSpawnTime() { return m_attribs.get<int32>(CreatureAttrSpawnTime); }
87+
88+ void setName(const std::string& name) { m_attribs.set(CreatureAttrName, name); }
89+ std::string getName() { return m_attribs.get<std::string>(CreatureAttrName); }
90+
91+ void setOutfit(const Outfit& o) { m_attribs.set(CreatureAttrOutfit, o); }
92+ Outfit getOutfit() { return m_attribs.get<Outfit>(CreatureAttrOutfit); }
93+
94+ void setDirection(Otc::Direction dir) { m_attribs.set(CreatureAttrDir, dir); }
95+ Otc::Direction getDirection() { return m_attribs.get<Otc::Direction>(CreatureAttrDir); }
96+
97+ void setRace(CreatureRace race) { m_attribs.set(CreatureAttrRace, race); }
98+ CreatureRace getRace() { return m_attribs.get<CreatureRace>(CreatureAttrRace); }
99+
100+ CreaturePtr cast();
101+
102+private:
103+ stdext::dynamic_storage<uint8> m_attribs;
104+};
105+
106+class CreatureManager
107+{
108+public:
109+ CreatureManager();
110+ void clear() { m_creatures.clear(); }
111+ void clearSpawns();
112+ void terminate();
113+
114+ void loadMonsters(const std::string& file);
115+ void loadSingleCreature(const std::string& file);
116+ void loadNpcs(const std::string& folder);
117+ void loadCreatureBuffer(const std::string& buffer);
118+ void loadSpawns(const std::string& fileName);
119+ void saveSpawns(const std::string& fileName);
120+
121+ const CreatureTypePtr& getCreatureByName(std::string name);
122+ const CreatureTypePtr& getCreatureByLook(int look);
123+
124+ std::vector<SpawnPtr> getSpawns();
125+ SpawnPtr getSpawn(const Position& centerPos);
126+ SpawnPtr getSpawnForPlacePos(const Position& pos);
127+ SpawnPtr addSpawn(const Position& centerPos, int radius);
128+ void deleteSpawn(const SpawnPtr& spawn);
129+
130+ bool isLoaded() { return m_loaded; }
131+ bool isSpawnLoaded() { return m_spawnLoaded; }
132+
133+ const std::vector<CreatureTypePtr>& getCreatures() { return m_creatures; }
134+
135+protected:
136+ void internalLoadCreatureBuffer(TiXmlElement* elem, const CreatureTypePtr& m);
137+
138+private:
139+ std::vector<CreatureTypePtr> m_creatures;
140+ std::unordered_map<Position, SpawnPtr, PositionHasher> m_spawns;
141+ stdext::boolean<false> m_loaded, m_spawnLoaded;
142+ CreatureTypePtr m_nullCreature;
143+};
144+
145+extern CreatureManager g_creatures;
146+
147+#endif
Top