1
/*
2
 *  The Mana World
3
 *  Copyright (C) 2004  The Mana World Development Team
4
 *
5
 *  This file is part of The Mana World.
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21
22
#include "animatedsprite.h"
23
#include "configuration.h"
24
#include "game.h"
25
#ifdef TMWSERV_SUPPORT
26
#include "guild.h"
27
#endif
28
#include "localplayer.h"
29
#include "particle.h"
30
#include "player.h"
31
#include "text.h"
32
33
#include "gui/palette.h"
34
35
#include "resources/colordb.h"
36
#include "resources/itemdb.h"
37
#include "resources/iteminfo.h"
38
39
#include "utils/stringutils.h"
40
41
Player::Player(int id, int job, Map *map, bool isNPC):
42
    Being(id, job, map),
43
    mGender(GENDER_UNSPECIFIED),
44
    mIsGM(false),
45
    mInParty(false)
46
{
47
    if (!isNPC)
48
    {
49
        for (int i = 0; i < VECTOREND_SPRITE; i++)
50
        {
51
            mSprites.push_back(NULL);
52
            mSpriteIDs.push_back(0);
53
            mSpriteColors.push_back("");
54
        }
55
56
        /* Human base sprite. When implementing different races remove this
57
         * line and set the base sprite when setting the race of the player
58
         * character.
59
         */
60
        setSprite(BASE_SPRITE, -100);
61
    }
62
    mShowName = config.getValue("visiblenames", 1);
63
    config.addListener("visiblenames", this);
64
65
    updateColors();
66
}
67
68
Player::~Player()
69
{
70
    config.removeListener("visiblenames", this);
71
}
72
73
#ifdef EATHENA_SUPPORT
74
void Player::logic()
75
{
76
    switch (mAction)
77
    {
78
        case STAND:
79
        case SIT:
80
        case DEAD:
81
        case HURT:
82
           break;
83
84
        case WALK:
85
            mFrame = (get_elapsed_time(mWalkTime) * 6) / getWalkSpeed();
86
            if (mFrame >= 6)
87
                nextStep();
88
            break;
89
90
        case ATTACK:
91
            int rotation = 0;
92
            std::string particleEffect = "";
93
            int frames = 4;
94
95
            if (mEquippedWeapon &&
96
                mEquippedWeapon->getAttackType() == ACTION_ATTACK_BOW)
97
            {
98
                frames = 5;
99
            }
100
101
            mFrame = (get_elapsed_time(mWalkTime) * frames) / mAttackSpeed;
102
103
            //attack particle effect
104
            if (mEquippedWeapon)
105
                particleEffect = mEquippedWeapon->getParticleEffect();
106
107
            if (!particleEffect.empty() && mParticleEffects && mFrame == 1)
108
            {
109
                switch (mDirection)
110
                {
111
                    case DOWN: rotation = 0; break;
112
                    case LEFT: rotation = 90; break;
113
                    case UP: rotation = 180; break;
114
                    case RIGHT: rotation = 270; break;
115
                    default: break;
116
                }
117
                Particle *p;
118
                p = particleEngine->addEffect("graphics/particles/" +
119
                                              particleEffect, 0, 0, rotation);
120
                controlParticle(p);
121
            }
122
123
            if (mFrame >= frames)
124
                nextStep();
125
126
            break;
127
    }
128
129
    Being::logic();
130
}
131
#endif
132
133
void Player::setGender(Gender gender)
134
{
135
    if (gender != mGender)
136
    {
137
        mGender = gender;
138
139
        // Reload all subsprites
140
        for (unsigned int i = 0; i < mSprites.size(); i++)
141
        {
142
            if (mSpriteIDs.at(i) != 0)
143
                setSprite(i, mSpriteIDs.at(i), mSpriteColors.at(i));
144
        }
145
    }
146
}
147
148
void Player::setGM(bool gm)
149
{
150
    mIsGM = gm;
151
152
    updateColors();
153
}
154
155
void Player::setSprite(unsigned int slot, int id, const std::string &color)
156
{
157
    assert(slot >= BASE_SPRITE && slot < VECTOREND_SPRITE);
158
159
    // id = 0 means unequip
160
    if (id == 0)
161
    {
162
        delete mSprites[slot];
163
        mSprites[slot] = NULL;
164
165
#ifdef EATHENA_SUPPORT
166
        if (slot == WEAPON_SPRITE)
167
            mEquippedWeapon = NULL;
168
#endif
169
    }
170
    else
171
    {
172
        std::string filename = ItemDB::get(id).getSprite(mGender);
173
        AnimatedSprite *equipmentSprite = NULL;
174
175
        if (!filename.empty())
176
        {
177
            if (!color.empty())
178
                filename += "|" + color;
179
180
            equipmentSprite = AnimatedSprite::load("graphics/sprites/" +
181
                                                   filename);
182
        }
183
184
        if (equipmentSprite)
185
            equipmentSprite->setDirection(getSpriteDirection());
186
187
        if (mSprites[slot])
188
            delete mSprites[slot];
189
190
        mSprites[slot] = equipmentSprite;
191
192
        if (slot == WEAPON_SPRITE)
193
            mEquippedWeapon = &ItemDB::get(id);
194
195
        setAction(mAction);
196
    }
197
198
    mSpriteIDs[slot] = id;
199
    mSpriteColors[slot] = color;
200
}
201
202
void Player::setSpriteID(unsigned int slot, int id)
203
{
204
    setSprite(slot, id, mSpriteColors[slot]);
205
}
206
207
void Player::setSpriteColor(unsigned int slot, const std::string &color)
208
{
209
    setSprite(slot, mSpriteIDs[slot], color);
210
}
211
212
#ifdef TMWSERV_SUPPORT
213
Guild* Player::addGuild(short guildId, short rights)
214
{
215
    Guild *guild = new Guild(guildId, rights);
216
    mGuilds.insert(std::pair<int, Guild*>(guildId, guild));
217
    return guild;
218
}
219
220
void Player::removeGuild(int id)
221
{
222
    mGuilds.erase(id);
223
}
224
225
Guild *Player::getGuild(const std::string &guildName) const
226
{
227
    std::map<int, Guild*>::const_iterator itr, itr_end = mGuilds.end();
228
    for (itr = mGuilds.begin(); itr != itr_end; ++itr)
229
    {
230
        Guild *guild = itr->second;
231
        if (guild->getName() == guildName)
232
        {
233
            return guild;
234
        }
235
    }
236
237
    return NULL;
238
}
239
240
Guild *Player::getGuild(int id) const
241
{
242
    std::map<int, Guild*>::const_iterator itr;
243
    itr = mGuilds.find(id);
244
    if (itr != mGuilds.end())
245
    {
246
        return itr->second;
247
    }
248
249
    return NULL;
250
}
251
252
short Player::getNumberOfGuilds()
253
{
254
    return mGuilds.size();
255
}
256
257
#endif
258
259
void Player::setInParty(bool inParty)
260
{
261
    mInParty = inParty;
262
263
    updateColors();
264
}
265
266
void Player::optionChanged(const std::string &value)
267
{
268
    if (value == "visiblenames")
269
    {
270
        setShowName(config.getValue("visiblenames", 1));
271
    }
272
}
273
274
void Player::updateColors()
275
{
276
    mTextColor = &guiPalette->getColor(Palette::PLAYER);
277
278
    if (mIsGM)
279
    {
280
        mTextColor = &guiPalette->getColor(Palette::GM);
281
        mNameColor = &guiPalette->getColor(Palette::GM_NAME);
282
    }
283
    else if (mInParty)
284
    {
285
        mNameColor = &guiPalette->getColor(Palette::PARTY);
286
    }
287
    else
288
    {
289
        mNameColor = &guiPalette->getColor(Palette::PC);
290
    }
291
}