summaryrefslogtreecommitdiff
path: root/src/being.cpp
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2005-10-09 03:34:45 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2005-10-09 03:34:45 +0000
commit8bde9095c5840b8d62ebafe11beaed98877d6ac2 (patch)
tree537f717a339d1247cae222eb7a354ea5dbe8babf /src/being.cpp
parenta246c08cef5e4d598fc07a681eb971bfbcf01519 (diff)
downloadmana-8bde9095c5840b8d62ebafe11beaed98877d6ac2.tar.gz
mana-8bde9095c5840b8d62ebafe11beaed98877d6ac2.tar.bz2
mana-8bde9095c5840b8d62ebafe11beaed98877d6ac2.tar.xz
mana-8bde9095c5840b8d62ebafe11beaed98877d6ac2.zip
* Made Sprite into an interface implemented by both FloorItem and Being, which
hook themselves into the map on construction. The improved fringe layer is working as expected now. * Made sure TMW compiles without warnings even when using "-Wconversion -Wshadow -Wcast-qual -Wwrite-strings -ansi -pedantic", lots of cleanups. * Added two new small tilesets that contain the desert tiles that are twice and three times the height of a normal tile. One well in new_3-1 has been converted to use the new double tiles for testing purposes.
Diffstat (limited to 'src/being.cpp')
-rw-r--r--src/being.cpp345
1 files changed, 270 insertions, 75 deletions
diff --git a/src/being.cpp b/src/being.cpp
index 5cdd8c01..9f9c7834 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -45,12 +45,41 @@
extern Being* autoTarget;
extern std::map<int, Spriteset*> monsterset;
+// From main.cpp
+extern Spriteset *hairset;
+extern Spriteset *playerset;
+
+// From engine.cpp
+extern Spriteset *emotionset;
+extern Spriteset *npcset;
+extern Spriteset *weaponset;
+
Being *player_node = NULL;
std::list<Being*> beings;
-PATH_NODE::PATH_NODE(Uint16 x, Uint16 y):
- x(x), y(y)
+char hairtable[16][4][2] = {
+ // S(x,y) W(x,y) N(x,y) E(x,y)
+ { { 0, 0}, {-1, 2}, {-1, 2}, { 0, 2} }, // STAND
+ { { 0, 2}, {-2, 3}, {-1, 2}, { 1, 3} }, // WALK 1st frame
+ { { 0, 3}, {-2, 4}, {-1, 3}, { 1, 4} }, // WALK 2nd frame
+ { { 0, 1}, {-2, 2}, {-1, 2}, { 1, 2} }, // WALK 3rd frame
+ { { 0, 2}, {-2, 3}, {-1, 2}, { 1, 3} }, // WALK 4th frame
+ { { 0, 1}, { 1, 2}, {-1, 3}, {-2, 2} }, // ATTACK 1st frame
+ { { 0, 1}, {-1, 2}, {-1, 3}, { 0, 2} }, // ATTACK 2nd frame
+ { { 0, 2}, {-4, 3}, { 0, 4}, { 3, 3} }, // ATTACK 3rd frame
+ { { 0, 2}, {-4, 3}, { 0, 4}, { 3, 3} }, // ATTACK 4th frame
+ { { 0, 0}, {-1, 2}, {-1, 2}, {-1, 2} }, // BOW_ATTACK 1st frame
+ { { 0, 0}, {-1, 2}, {-1, 2}, {-1, 2} }, // BOW_ATTACK 2nd frame
+ { { 0, 0}, {-1, 2}, {-1, 2}, {-1, 2} }, // BOW_ATTACK 3rd frame
+ { { 0, 0}, {-1, 2}, {-1, 2}, {-1, 2} }, // BOW_ATTACK 4th frame
+ { { 0, 4}, {-1, 6}, {-1, 6}, { 0, 6} }, // SIT
+ { { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} }, // ?? HIT
+ { { 0, 16}, {-1, 6}, {-1, 6}, { 0, 6} } // DEAD
+};
+
+PATH_NODE::PATH_NODE(Uint16 iX, Uint16 iY):
+ x(iX), y(iY)
{
}
@@ -161,16 +190,15 @@ void sort() {
Being::Being():
job(0),
x(0), y(0), direction(SOUTH),
- action(0), frame(0),
+ action(0), mFrame(0),
speech_color(0),
walk_time(0),
speed(150),
emotion(0), emotion_time(0),
- text_x(0), text_y(0),
aspd(350),
- m_weapon(0),
- m_id(0),
- map(0),
+ mWeapon(0),
+ mId(0),
+ mMap(NULL),
hairStyle(1), hairColor(1),
speech_time(0),
damage_time(0),
@@ -181,24 +209,25 @@ Being::Being():
Being::~Being()
{
clearPath();
+ setMap(NULL);
}
void Being::setDestination(Uint16 destX, Uint16 destY)
{
- if (!map)
- return;
-
- setPath(map->findPath(x, y, destX, destY));
+ if (mMap)
+ {
+ setPath(mMap->findPath(x, y, destX, destY));
+ }
}
void Being::clearPath()
{
- path.clear();
+ mPath.clear();
}
void Being::setPath(std::list<PATH_NODE> path)
{
- this->path = path;
+ mPath = path;
if (action != WALK && action != DEAD)
{
@@ -257,21 +286,33 @@ void Being::setDamage(Sint16 amount, Uint32 time)
void Being::setMap(Map *map)
{
- this->map = map;
+ // Remove sprite from potential previous map
+ if (mMap != NULL)
+ {
+ mMap->removeSprite(mSpriteIterator);
+ }
+
+ mMap = map;
+
+ // Add sprite to potential new map
+ if (mMap != NULL)
+ {
+ mSpriteIterator = mMap->addSprite(this);
+ }
}
void Being::nextStep()
{
- frame = 0;
+ mFrame = 0;
- if (path.empty())
+ if (mPath.empty())
{
action = STAND;
return;
}
- PATH_NODE node = path.front();
- path.pop_front();
+ PATH_NODE node = mPath.front();
+ mPath.pop_front();
if (node.x > x) {
if (node.y > y) direction = SE;
@@ -296,57 +337,74 @@ void Being::nextStep()
void Being::logic()
{
- if (get_elapsed_time(speech_time) > 5000) {
+ // Determine whether speech should still be displayed
+ if (get_elapsed_time(speech_time) > 5000)
+ {
showSpeech = false;
}
- if (get_elapsed_time(damage_time) > 3000) {
- showDamage = false;
- }
- if (getType() != PLAYER)
+ // Determine whether damange should still be displayed
+ if (get_elapsed_time(damage_time) > 3000)
{
- return;
+ showDamage = false;
}
- switch (action) {
- case WALK:
- frame = (get_elapsed_time(walk_time) * 4) / speed;
- if (frame >= 4) {
- nextStep();
- }
- break;
- case ATTACK:
- frame = (get_elapsed_time(walk_time) * 4) / aspd;
- if (frame >= 4) {
- nextStep();
- if (autoTarget && this == player_node) {
- attack(autoTarget);
+ // Execute next walk or attack command for players
+ if (getType() == PLAYER)
+ {
+ switch (action) {
+ case WALK:
+ mFrame = (get_elapsed_time(walk_time) * 4) / speed;
+ if (mFrame >= 4) {
+ nextStep();
+ }
+ break;
+ case ATTACK:
+ mFrame = (get_elapsed_time(walk_time) * 4) / aspd;
+ if (mFrame >= 4) {
+ nextStep();
+ if (autoTarget && this == player_node) {
+ attack(autoTarget);
+ }
}
+ break;
+ }
+
+ if (emotion != 0)
+ {
+ emotion_time--;
+ if (emotion_time == 0) {
+ emotion = 0;
}
- break;
+ }
}
- if (emotion != 0) {
- emotion_time--;
- if (emotion_time == 0) {
- emotion = 0;
- }
+ // Update pixel coordinates
+ mPx = x * 32;
+ mPy = y * 32;
+
+ if (getType() == PLAYER || getType() == MONSTER)
+ {
+ mPy += getYOffset();
+ mPx += getXOffset();
}
}
-void Being::drawSpeech(Graphics *graphics)
+void Being::drawSpeech(Graphics *graphics, Sint32 offsetX, Sint32 offsetY)
{
+ int px = mPx + offsetX;
+ int py = mPy + offsetY;
+
// Draw speech above this being
- if (showSpeech) {
+ if (showSpeech)
+ {
graphics->setFont(speechFont);
- graphics->drawText(speech,
- text_x + 18, text_y - 60,
- gcn::Graphics::CENTER);
-
- // Backing to default font
- graphics->setFont(gui->getFont());
+ graphics->drawText(speech, px + 18, py - 60, gcn::Graphics::CENTER);
}
- if (showDamage) {
+
+ // Draw damage above this being
+ if (showDamage)
+ {
// Selecting the right color
if (damage == "miss")
{
@@ -361,28 +419,23 @@ void Being::drawSpeech(Graphics *graphics)
graphics->setFont(hitRedFont);
}
- int textX = 0;
- int textY = 0;
- if (getType() == PLAYER) {
- textX = 16;
- textY = 70;
- }
- else {
- textX = 60;
- textY = 0;
- }
+ int textY = (getType() == PLAYER) ? 70 : 32;
graphics->drawText(damage,
- text_x + textX,
- text_y - textY - get_elapsed_time(damage_time) / 100,
- gcn::Graphics::CENTER);
+ px + 16,
+ py - textY - get_elapsed_time(damage_time) / 100,
+ gcn::Graphics::CENTER);
+ }
- // Backing to default font
- graphics->setFont(gui->getFont());
+ // Draw player name
+ if (getType() == PLAYER && this != player_node)
+ {
+ graphics->setFont(speechFont);
+ graphics->drawText(mName, px + 15, py + 30, gcn::Graphics::CENTER);
}
}
-Being::Type Being::getType()
+Being::Type Being::getType() const
{
if (job < 10) {
return PLAYER;
@@ -395,11 +448,6 @@ Being::Type Being::getType()
}
}
-void Being::setWeapon(Uint16 weapon)
-{
- m_weapon = weapon;
-}
-
void Being::setWeaponById(Uint16 weapon)
{
switch (weapon)
@@ -430,7 +478,154 @@ void Being::setWeaponById(Uint16 weapon)
}
}
-void Being::setId(Uint32 id)
+int
+Being::getXOffset() const
+{
+ int offset = 0;
+
+ if (action == WALK)
+ {
+ if (direction != NORTH && direction != SOUTH)
+ {
+ offset = (get_elapsed_time(walk_time) * 32) / speed;
+ if (offset > 32) offset = 32;
+
+ if (direction == WEST || direction == NW || direction == SW) {
+ offset = -offset;
+ offset += 32;
+ }
+ else {
+ offset -= 32;
+ }
+ }
+ }
+
+ return offset;
+}
+
+int
+Being::getYOffset() const
+{
+ int offset = 0;
+
+ if (action == WALK)
+ {
+ if (direction != EAST && direction != WEST)
+ {
+ offset = (get_elapsed_time(walk_time) * 32) / speed;
+ if (offset > 32) offset = 32;
+
+ if (direction == NORTH || direction == NW || direction == NE) {
+ offset = -offset;
+ offset += 32;
+ }
+ else {
+ offset -= 32;
+ }
+ }
+ }
+
+ return offset;
+}
+
+void
+Being::draw(Graphics *graphics, int offsetX, int offsetY)
{
- m_id = id;
+ unsigned char dir = direction / 2;
+ int px = mPx + offsetX;
+ int py = mPy + offsetY;
+ int frame;
+
+ switch (getType())
+ {
+ case PLAYER:
+ if (action == SIT || action == DEAD)
+ {
+ frame = 0;
+ }
+
+ frame = mFrame + action;
+
+ if (action == ATTACK && getWeapon() > 0)
+ {
+ frame += 4 * (getWeapon() - 1);
+ }
+
+ graphics->drawImage(playerset->spriteset[frame + 16 * dir],
+ px - 16, py - 32);
+
+ if (getWeapon() != 0 && action == ATTACK)
+ {
+ Image *image = weaponset->spriteset[
+ 16 * (getWeapon() - 1) + 4 * mFrame + dir];
+
+ graphics->drawImage(image, px - 64, py - 80);
+ }
+
+ if (getHairColor() <= NR_HAIR_COLORS)
+ {
+ int hf = getHairColor() - 1 + 10 * (dir + 4 *
+ (getHairStyle() - 1));
+
+ graphics->drawImage(hairset->spriteset[hf],
+ px - 2 + 2 * hairtable[frame][dir][0],
+ py - 50 + 2 * hairtable[frame][dir][1]);
+ }
+
+ if (emotion != 0)
+ {
+ graphics->drawImage(emotionset->spriteset[emotion - 1],
+ px + 3, py - 90);
+ }
+ break;
+
+ case NPC:
+ graphics->drawImage(npcset->spriteset[job - 100], px - 8, py - 52);
+ break;
+
+ case MONSTER:
+ if (mFrame >= 4)
+ {
+ mFrame = 3;
+ }
+
+ px -= 42;
+ py -= 65;
+
+ frame = mFrame + action;
+
+ if (action == MONSTER_DEAD)
+ {
+ graphics->drawImage(
+ monsterset[job - 1002]->spriteset[dir + 4 * MONSTER_DEAD],
+ px + 30, py + 40);
+ }
+ else
+ {
+ graphics->drawImage(
+ monsterset[job-1002]->spriteset[dir + 4 * frame],
+ px + 30, py + 40);
+
+ /*
+ if (x == mouseTileX && y == mouseTileY)
+ {
+ graphics->drawImage(attackTarget, px + 30 + 16, py + 32);
+ }
+ */
+ }
+
+ if (action != STAND)
+ {
+ mFrame = (get_elapsed_time(walk_time) * 4) / speed;
+
+ if (mFrame >= 4 && action != MONSTER_DEAD)
+ {
+ nextStep();
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
}