summaryrefslogtreecommitdiff
path: root/src/game-server/monster.hpp
blob: 3f6db5c1263db8009bd9d73f05b7bdea6a8843f7 (plain) (blame)
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
236
237
238
239
240
241
/*
 *  The Mana World Server
 *  Copyright 2004 The Mana World Development Team
 *
 *  This file is part of The Mana World.
 *
 *  The Mana World  is free software; you can redistribute  it and/or modify it
 *  under the terms of the GNU General  Public License as published by the Free
 *  Software Foundation; either version 2 of the License, or any later version.
 *
 *  The Mana  World is  distributed in  the hope  that it  will be  useful, but
 *  WITHOUT ANY WARRANTY; without even  the implied warranty of MERCHANTABILITY
 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 *  more details.
 *
 *  You should  have received a  copy of the  GNU General Public  License along
 *  with The Mana  World; if not, write to the  Free Software Foundation, Inc.,
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 *  $Id$
 */

#ifndef _TMWSERV_MONSTER_H_
#define _TMWSERV_MONSTER_H_

#include <map>
#include <vector>

#include "game-server/being.hpp"
#include "game-server/eventlistener.hpp"

class ItemClass;
class MapComposite;

/**
 * Structure containing an item class and its probability to be dropped (unit: 1/10000).
 */
struct MonsterDrop
{
    ItemClass *item;
    int probability;
};

typedef std::vector< MonsterDrop > MonsterDrops;

/**
 * Structure containing different attack types of a monster type
 */
struct MonsterAttack
{
    unsigned id;
    int priority;
    float damageFactor;
    int element;
    int type;
    int preDelay;
    int aftDelay;
    int range;
    int angle;
};

typedef std::vector< MonsterAttack *> MonsterAttacks;

/**
 * Class describing the characteristics of a generic monster.
 */
class MonsterClass
{
    public:
        MonsterClass(int id):
            mID(id),
            mAttributes(BASE_ATTR_NB, 0),
            mSpeed(1),
            mSize(16),
            mExp(-1),
            mAggressive(false),
            mTrackRange(1),
            mStrollRange(0),
            mMutation(0),
            mAttackDistance(0)
        {}

        /**
         * Gets monster type.
         */
        int getType() const
        { return mID; }

        /**
         * Sets monster drops.
         */
        void setDrops(MonsterDrops const &v)
        { mDrops = v; }

        /**
         * Sets a being attribute
         */
        void setAttribute(size_t attribute, int value)
        { mAttributes.at(attribute) = value ; }

        /**
         * Gets a being attribute
         */
        int getAttribute(size_t attribute) const
        { return mAttributes.at(attribute); }

        void setSpeed(int speed) { mSpeed = speed; } /**< sets inverted movement speed*/
        int getSpeed() const { return mSpeed; } /**< gets inverted movement speed*/

        void setSize(int size) { mSize = size; } /**< sets hit circle radius*/
        int getSize() const { return mSize; } /**< gets hit circle radius*/

        void setExp(int exp) { mExp = exp; } /**< sets experience reward*/
        int getExp() const { return mExp; } /**< gets experience reward*/

        void setAggressive(bool aggressive) { mAggressive = aggressive; } /**< sets if the monster attacks without being attacked first*/
        bool isAggressive() const { return mAggressive; } /**< gets if the monster attacks without being attacked first*/

        void setTrackRange(unsigned range){ mTrackRange = range; } /**< sets range in tiles in which the monster searches for enemies*/
        unsigned getTrackRange() const { return mTrackRange; } /**< gets range in tiles in which the monster searches for enemies*/

        void setStrollRange(unsigned range) { mStrollRange = range; } /**< sets range in tiles in which the monster moves around when idled*/
        unsigned getStrollRange() const { return mStrollRange; } /**< gets range in tiles in which the monster moves around when idled*/

        void setMutation(unsigned factor) { mMutation = factor; } /**< sets mutation factor in percent*/
        unsigned getMutation() const { return mMutation; } /**< gets mutation factor in percent*/

        void setAttackDistance(unsigned distance) { mAttackDistance = distance; } /**< sets preferred combat distance in pixels*/
        unsigned getAttackDistance() const { return mAttackDistance; } /**< gets preferred combat distance in pixels*/

        void addAttack(MonsterAttack *type) { mAttacks.push_back(type); } /**< adds an attack to the monsters repertoire */
        const MonsterAttacks &getAttacks() const { return mAttacks; } /**< gets all attacks of the monster */

        /**
         * Randomly selects a monster drop (may return NULL).
         */
        ItemClass *getRandomDrop() const;

    private:
        unsigned short mID; /**< ID of the monster class. */
        MonsterDrops mDrops; /**< Items the monster drops when dying. */
        std::vector<int> mAttributes; /**< Base attributes of the monster*/
        int mSpeed; /** (inverted) Movement speed of the monster */
        int mSize; /** Collision circle radius of the monster */
        int mExp; /**< Exp reward for killing the monster */
        bool mAggressive;       /**< Does the monster attack without being provoked? */
        unsigned mTrackRange;   /**< Distance the monster tracks enemies in */
        unsigned mStrollRange;  /**< Distance the monster strolls around in when not fighting */
        unsigned mMutation;     /**< Mutation factor in percent*/
        unsigned mAttackDistance;
        MonsterAttacks mAttacks; /**< preferred combat distance in pixels*/
};

/**
 * Structure holding possible positions relative to the target from which
 * the monster can attack
 */
struct AttackPosition
{
    AttackPosition(int posX, int posY, Direction dir):
        x(posX),
        y(posY),
        direction(dir)
    {};

    int x;
    int y;
    Direction direction;
};

/**
 * The class for a fightable monster with its own AI
 */
class Monster : public Being
{
    public:

        static const int KILLSTEAL_PROTECTION_TIME = 100; /**< Time in game ticks until ownership of a monster can change */

        /**
         * Constructor.
         */
        Monster(MonsterClass *);

        /**
         * Destructor.
         */
        ~Monster();

        /**
         * Gets monster specy.
         */
        MonsterClass *getSpecy()
        { return mSpecy; }

        /**
         * Performs one step of controller logic.
         */
        void update();

        /**
         * Performs an attack, if needed.
         */
        void perform();

        /**
         * Kills the being.
         */
        void died();

        /**
         * Calls the damage function in Being and updates the aggro list
         */
        virtual int damage(Object *source, Damage const &damage);

        /**
         * Removes a being from the anger list.
         */
        void forgetTarget(Thing *being);

    private:
        int calculatePositionPriority(Point position, int targetPriority);

        MonsterClass *mSpecy; /**< Monster specy. */
        int mCountDown; /**< Count down till next random movement (temporary). */
        std::map<Being *, int> mAnger;   /**< Aggression towards other beings */
        EventListener mTargetListener; /**< Listener for updating the anger list. */

        Character* mOwner; /**< Character who currently owns this monster (killsteal protection) */
        int mOwnerTimer; /**< Time until someone else can claim this monster (killsteal protection) */
        std::map<Character *, std::set <size_t> > mExpReceivers; /**< List of characters and their skills that attacked this monster*/
        std::set<Character *> mLegalExpReceivers; /**< List of characters who are entitled to receive exp (killsteal protection)*/

        int mAttackTime;                       /**< Delay until monster can attack */
        MonsterAttack *mCurrentAttack; /**<Attack the monster is currently performing */
        std::list<AttackPosition> mAttackPositions; /**< set positions relative to target from which the monster can attack */

        friend struct MonsterTargetEventDispatch;
};

#endif // _TMWSERV_MONSTER_H_