summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJared Adams <jaxad0127@gmail.com>2010-04-13 22:48:28 -0600
committerJared Adams <jaxad0127@gmail.com>2010-04-16 17:42:45 -0600
commit11a6f342e579c26320334b9ae9735701386e3b25 (patch)
tree5de9a3647f881a1f27f4dc31054ad086bdc86d84
parent9f6c1f0bd9d2ef9a3be35fee2c488d8ea6c09d6d (diff)
downloadmana-11a6f342e579c26320334b9ae9735701386e3b25.tar.gz
mana-11a6f342e579c26320334b9ae9735701386e3b25.tar.bz2
mana-11a6f342e579c26320334b9ae9735701386e3b25.tar.xz
mana-11a6f342e579c26320334b9ae9735701386e3b25.zip
Add race support for eAthena
The job/class field is used to select the race. If the given race isn't defined, it falls back on the first race (so servers can use jobs/classes without races). Also rename job to subtype for Being and subclasses, and begin support for changing monster and NPC subtypes on the fly (particle effects still need to be reset when they change). Reviewed-by: Bertram
-rw-r--r--src/being.cpp4
-rw-r--r--src/being.h14
-rw-r--r--src/localplayer.cpp4
-rw-r--r--src/localplayer.h2
-rw-r--r--src/monster.cpp69
-rw-r--r--src/monster.h4
-rw-r--r--src/net/ea/beinghandler.cpp4
-rw-r--r--src/net/ea/charserverhandler.cpp2
-rw-r--r--src/npc.cpp40
-rw-r--r--src/npc.h4
-rw-r--r--src/player.cpp21
-rw-r--r--src/player.h4
-rw-r--r--src/resources/itemdb.cpp11
-rw-r--r--src/resources/itemdb.h2
-rw-r--r--src/resources/iteminfo.h28
15 files changed, 129 insertions, 84 deletions
diff --git a/src/being.cpp b/src/being.cpp
index 44293732..47c31c36 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -67,14 +67,14 @@ static const int DEFAULT_BEING_HEIGHT = 32;
int Being::mNumberOfHairstyles = 1;
// TODO: mWalkTime used by eAthena only
-Being::Being(int id, int job, Map *map):
+Being::Being(int id, int subtype, Map *map):
mFrame(0),
mWalkTime(0),
mEmotion(0), mEmotionTime(0),
mSpeechTime(0),
mAttackSpeed(350),
mAction(STAND),
- mJob(job),
+ mSubType(subtype),
mId(id),
mDirection(DOWN),
mSpriteDirection(DIRECTION_DOWN),
diff --git a/src/being.h b/src/being.h
index 3479a9a8..3d3dfa71 100644
--- a/src/being.h
+++ b/src/being.h
@@ -118,11 +118,11 @@ class Being : public Sprite, public ConfigListener
/**
* Constructor.
*
- * @param id a unique being id
- * @param job partly determines the type of the being
- * @param map the map the being is on
+ * @param id a unique being id
+ * @param subtype partly determines the type of the being
+ * @param map the map the being is on
*/
- Being(int id, int job, Map *map);
+ Being(int id, int subtype, Map *map);
virtual ~Being();
@@ -284,12 +284,12 @@ class Being : public Sprite, public ConfigListener
/**
* Return Being's current Job (player job, npc, monster, creature )
*/
- Uint16 getJob() const { return mJob; }
+ Uint16 getSubType() const { return mSubType; }
/**
* Set Being's current Job (player job, npc, monster, creature )
*/
- void setJob(Uint16 job) { mJob = job; }
+ virtual void setSubtype(Uint16 subtype) { mSubType = subtype; }
/**
* Sets the walk speed.
@@ -611,7 +611,7 @@ class Being : public Sprite, public ConfigListener
int mAttackSpeed; /**< Attack speed */
Action mAction; /**< Action the being is performing */
- Uint16 mJob; /**< Job (player job, npc, monster, creature ) */
+ Uint16 mSubType; /**< Subtype (graphical view, basically) */
int mId; /**< Unique sprite id */
Uint8 mDirection; /**< Facing direction */
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index ef2d7e4e..961248dc 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -75,8 +75,8 @@ const short walkingKeyboardDelay = 1000;
LocalPlayer *player_node = NULL;
-LocalPlayer::LocalPlayer(int id, int job):
- Player(id, job, 0),
+LocalPlayer::LocalPlayer(int id, int subtype):
+ Player(id, subtype, 0),
mEquipment(new Equipment),
mAttackRange(0),
mTargetTime(-1),
diff --git a/src/localplayer.h b/src/localplayer.h
index 65653d50..dd7b94d4 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -105,7 +105,7 @@ class LocalPlayer : public Player
/**
* Constructor.
*/
- LocalPlayer(int id= 65535, int job = 0);
+ LocalPlayer(int id= 65535, int subtype = 0);
/**
* Destructor.
diff --git a/src/monster.cpp b/src/monster.cpp
index 23be9395..0876b08d 100644
--- a/src/monster.cpp
+++ b/src/monster.cpp
@@ -35,37 +35,11 @@
#include "resources/monsterdb.h"
#include "resources/monsterinfo.h"
-Monster::Monster(int id, int job, Map *map):
- Being(id, job, map),
+Monster::Monster(int id, int subtype, Map *map):
+ Being(id, subtype, map),
mAttackType(1)
{
- const MonsterInfo &info = getInfo();
-
- // Setup Monster sprites
- const std::list<std::string> &sprites = info.getSprites();
-
- for (std::list<std::string>::const_iterator i = sprites.begin();
- i != sprites.end(); i++)
- {
- std::string file = "graphics/sprites/" + *i;
- mSprites.push_back(AnimatedSprite::load(file));
- }
-
- // Ensure that something is shown
- if (mSprites.size() == 0)
- {
- mSprites.push_back(AnimatedSprite::load("graphics/sprites/error.xml"));
- }
-
- if (Particle::enabled)
- {
- const std::list<std::string> &particleEffects = info.getParticleEffects();
- for (std::list<std::string>::const_iterator i = particleEffects.begin();
- i != particleEffects.end(); i++)
- {
- controlParticle(particleEngine->addEffect((*i), 0, 0));
- }
- }
+ setSubtype(subtype);
mNameColor = &userPalette->getColor(UserPalette::MONSTER);
mTextColor = &userPalette->getColor(UserPalette::MONSTER);
@@ -86,6 +60,7 @@ void Monster::logic()
Being::logic();
}
+
void Monster::setAction(Action action, int attackType)
{
SpriteAction currentAction = ACTION_INVALID;
@@ -144,6 +119,40 @@ void Monster::setAction(Action action, int attackType)
}
}
+void Monster::setSubtype(Uint16 subtype)
+{
+ Being::setSubtype(subtype);
+
+ const MonsterInfo &info = getInfo();
+
+ // Setup Monster sprites
+ const std::list<std::string> &sprites = info.getSprites();
+
+ mSprites.clear();
+ for (std::list<std::string>::const_iterator i = sprites.begin();
+ i != sprites.end(); i++)
+ {
+ std::string file = "graphics/sprites/" + *i;
+ mSprites.push_back(AnimatedSprite::load(file));
+ }
+
+ // Ensure that something is shown
+ if (mSprites.size() == 0)
+ {
+ mSprites.push_back(AnimatedSprite::load("graphics/sprites/error.xml"));
+ }
+
+ if (Particle::enabled)
+ {
+ const std::list<std::string> &particleEffects = info.getParticleEffects();
+ for (std::list<std::string>::const_iterator i = particleEffects.begin();
+ i != particleEffects.end(); i++)
+ {
+ controlParticle(particleEngine->addEffect((*i), 0, 0));
+ }
+ }
+}
+
void Monster::handleAttack(Being *victim, int damage, AttackType type)
{
Being::handleAttack(victim, damage, type);
@@ -170,7 +179,7 @@ Being::TargetCursorSize Monster::getTargetCursorSize() const
const MonsterInfo &Monster::getInfo() const
{
- return MonsterDB::get(mJob);
+ return MonsterDB::get(mSubType);
}
void Monster::updateCoords()
diff --git a/src/monster.h b/src/monster.h
index 6fb82c7f..9bb8e3b9 100644
--- a/src/monster.h
+++ b/src/monster.h
@@ -30,7 +30,7 @@ class Text;
class Monster : public Being
{
public:
- Monster(int id, int job, Map *map);
+ Monster(int id, int subtype, Map *map);
virtual void logic();
@@ -38,6 +38,8 @@ class Monster : public Being
virtual Type getType() const { return MONSTER; }
+ virtual void setSubtype(Uint16 subtype);
+
virtual TargetCursorSize
getTargetCursorSize() const;
diff --git a/src/net/ea/beinghandler.cpp b/src/net/ea/beinghandler.cpp
index 6dcf9631..649e93e8 100644
--- a/src/net/ea/beinghandler.cpp
+++ b/src/net/ea/beinghandler.cpp
@@ -167,7 +167,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
if (speed == 0) { speed = 150; }
dstBeing->setWalkSpeed(Vector(speed, speed, 0));
- dstBeing->setJob(job);
+ dstBeing->setSubtype(job);
hairStyle = msg.readInt16();
weapon = msg.readInt16();
headBottom = msg.readInt16();
@@ -550,7 +550,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg)
}
dstBeing->setWalkSpeed(Vector(speed, speed, 0));
- dstBeing->setJob(job);
+ dstBeing->setSubtype(job);
hairStyle = msg.readInt16();
weapon = msg.readInt16();
shield = msg.readInt16();
diff --git a/src/net/ea/charserverhandler.cpp b/src/net/ea/charserverhandler.cpp
index 64e1d427..8706727a 100644
--- a/src/net/ea/charserverhandler.cpp
+++ b/src/net/ea/charserverhandler.cpp
@@ -220,7 +220,7 @@ LocalPlayer *CharServerHandler::readPlayerData(Net::MessageIn &msg, int *slot)
tempPlayer->setMP(msg.readInt16());
tempPlayer->setMaxMP(msg.readInt16());
msg.readInt16(); // speed
- msg.readInt16(); // class
+ tempPlayer->setSubtype(msg.readInt16()); // class (used for race)
int hairStyle = msg.readInt16();
Uint16 weapon = msg.readInt16();
tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true);
diff --git a/src/npc.cpp b/src/npc.cpp
index 29a6c61c..cdfe5193 100644
--- a/src/npc.cpp
+++ b/src/npc.cpp
@@ -37,11 +37,32 @@
#include "resources/npcdb.h"
-NPC::NPC(int id, int job, Map *map):
- Player(id, job, map, true)
+NPC::NPC(int id, int subtype, Map *map):
+ Player(id, subtype, map, true)
{
- NPCInfo info = NPCDB::get(job);
+ setSubtype(subtype);
+ setShowName(true);
+}
+
+void NPC::setName(const std::string &name)
+{
+ const std::string displayName = name.substr(0, name.find('#', 0));
+
+ Being::setName(displayName);
+
+ mNameColor = &userPalette->getColor(UserPalette::NPC);
+
+ mDispName->setColor(mNameColor);
+}
+
+void NPC::setSubtype(Uint16 subtype)
+{
+ Being::setSubtype(subtype);
+
+ NPCInfo info = NPCDB::get(subtype);
+
+ mSprites.clear();
// Setup NPC sprites
for (std::list<NPCsprite*>::const_iterator i = info.sprites.begin();
i != info.sprites.end();
@@ -65,19 +86,6 @@ NPC::NPC(int id, int job, Map *map):
this->controlParticle(p);
}
}
-
- setShowName(true);
-}
-
-void NPC::setName(const std::string &name)
-{
- const std::string displayName = name.substr(0, name.find('#', 0));
-
- Being::setName(displayName);
-
- mNameColor = &userPalette->getColor(UserPalette::NPC);
-
- mDispName->setColor(mNameColor);
}
void NPC::talk()
diff --git a/src/npc.h b/src/npc.h
index c7db58f1..0abd2395 100644
--- a/src/npc.h
+++ b/src/npc.h
@@ -30,12 +30,14 @@ class Text;
class NPC : public Player
{
public:
- NPC(int id, int job, Map *map);
+ NPC(int id, int subtype, Map *map);
void setName(const std::string &name);
virtual Type getType() const { return Being::NPC; }
+ virtual void setSubtype(Uint16 subtype);
+
void talk();
void setSprite(unsigned int slot, int id,
diff --git a/src/player.cpp b/src/player.cpp
index ad8c1db4..9113b4ab 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -43,8 +43,8 @@
#include "utils/stringutils.h"
-Player::Player(int id, int job, Map *map, bool isNPC):
- Being(id, job, map),
+Player::Player(int id, int subtype, Map *map, bool isNPC):
+ Being(id, subtype, map),
mGender(GENDER_UNSPECIFIED),
mParty(NULL),
mIsGM(false)
@@ -58,11 +58,7 @@ Player::Player(int id, int job, Map *map, bool isNPC):
mSpriteColors.push_back("");
}
- /* Human base sprite. When implementing different races remove this
- * line and set the base sprite when setting the race of the player
- * character.
- */
- setSprite(Net::getCharHandler()->baseSprite(), -100);
+ setSubtype(subtype);
}
mShowName = config.getValue("visiblenames", 1);
config.addListener("visiblenames", this);
@@ -137,6 +133,17 @@ void Player::logic()
Being::logic();
}
+void Player::setSubtype(Uint16 subtype)
+{
+ Being::setSubtype(subtype);
+
+ int id = -100 - subtype;
+ if (ItemDB::exists(id)) // Prevent showing errors when sprite doesn't exist
+ setSprite(Net::getCharHandler()->baseSprite(), id);
+ else
+ setSprite(Net::getCharHandler()->baseSprite(), -100);
+}
+
void Player::setGender(Gender gender)
{
if (gender != mGender)
diff --git a/src/player.h b/src/player.h
index 670f6d84..e75870a0 100644
--- a/src/player.h
+++ b/src/player.h
@@ -47,7 +47,7 @@ class Player : public Being
/**
* Constructor.
*/
- Player(int id, int job, Map *map, bool isNPC = false);
+ Player(int id, int subtype, Map *map, bool isNPC = false);
~Player();
@@ -55,6 +55,8 @@ class Player : public Being
virtual Type getType() const { return PLAYER; }
+ virtual void setSubtype(Uint16 subtype);
+
/**
* Sets the gender of this being.
*/
diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp
index d60e38da..4638f00e 100644
--- a/src/resources/itemdb.cpp
+++ b/src/resources/itemdb.cpp
@@ -78,6 +78,8 @@ static ItemType itemTypeFromString(const std::string &name, int id = 0)
else if (name=="equip-necklace") return ITEM_EQUIPMENT_NECKLACE;
else if (name=="equip-feet") return ITEM_EQUIPMENT_FEET;
else if (name=="equip-ammo") return ITEM_EQUIPMENT_AMMO;
+ else if (name=="racesprite") return ITEM_SPRITE_RACE;
+ else if (name=="hairsprite") return ITEM_SPRITE_HAIR;
else return ITEM_UNUSABLE;
}
@@ -255,6 +257,15 @@ void ItemDB::unload()
mLoaded = false;
}
+bool ItemDB::exists(int id)
+{
+ assert(mLoaded);
+
+ ItemInfos::const_iterator i = mItemInfos.find(id);
+
+ return i != mItemInfos.end();
+}
+
const ItemInfo &ItemDB::get(int id)
{
assert(mLoaded);
diff --git a/src/resources/itemdb.h b/src/resources/itemdb.h
index 63c016ba..be023073 100644
--- a/src/resources/itemdb.h
+++ b/src/resources/itemdb.h
@@ -43,6 +43,8 @@ namespace ItemDB
*/
void unload();
+ bool exists(int id);
+
const ItemInfo &get(int id);
const ItemInfo &get(const std::string &name);
diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h
index e14d62b8..a7c0ddca 100644
--- a/src/resources/iteminfo.h
+++ b/src/resources/iteminfo.h
@@ -72,19 +72,21 @@ enum EquipmentSlot
enum ItemType
{
ITEM_UNUSABLE = 0,
- ITEM_USABLE, // 1
- ITEM_EQUIPMENT_ONE_HAND_WEAPON, // 2
- ITEM_EQUIPMENT_TWO_HANDS_WEAPON,// 3
- ITEM_EQUIPMENT_TORSO,// 4
- ITEM_EQUIPMENT_ARMS,// 5
- ITEM_EQUIPMENT_HEAD,// 6
- ITEM_EQUIPMENT_LEGS,// 7
- ITEM_EQUIPMENT_SHIELD,// 8
- ITEM_EQUIPMENT_RING,// 9
- ITEM_EQUIPMENT_NECKLACE,// 10
- ITEM_EQUIPMENT_FEET,// 11
- ITEM_EQUIPMENT_AMMO,// 12
- ITEM_EQUIPMENT_CHARM// 13
+ ITEM_USABLE,
+ ITEM_EQUIPMENT_ONE_HAND_WEAPON,
+ ITEM_EQUIPMENT_TWO_HANDS_WEAPON,
+ ITEM_EQUIPMENT_TORSO,
+ ITEM_EQUIPMENT_ARMS, // 5
+ ITEM_EQUIPMENT_HEAD,
+ ITEM_EQUIPMENT_LEGS,
+ ITEM_EQUIPMENT_SHIELD,
+ ITEM_EQUIPMENT_RING,
+ ITEM_EQUIPMENT_NECKLACE, // 10
+ ITEM_EQUIPMENT_FEET,
+ ITEM_EQUIPMENT_AMMO,
+ ITEM_EQUIPMENT_CHARM,
+ ITEM_SPRITE_RACE,
+ ITEM_SPRITE_HAIR // 15
};
/**