diff options
-rw-r--r-- | src/being.cpp | 135 | ||||
-rw-r--r-- | src/being.h | 44 | ||||
-rw-r--r-- | src/engine.cpp | 46 | ||||
-rw-r--r-- | src/game.cpp | 141 | ||||
-rw-r--r-- | src/gui/setup.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 20 | ||||
-rw-r--r-- | src/map.cpp | 22 | ||||
-rw-r--r-- | src/map.h | 4 | ||||
-rw-r--r-- | src/net/protocol.h | 2 | ||||
-rw-r--r-- | src/sound.cpp | 5 |
10 files changed, 195 insertions, 226 deletions
diff --git a/src/being.cpp b/src/being.cpp index 6ae01f77..93496ea6 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -30,18 +30,10 @@ Being *player_node = NULL; std::list<Being*> beings; PATH_NODE::PATH_NODE(unsigned short x, unsigned short y): - x(x), y(y), next(NULL) + x(x), y(y) { } -void empty() { - std::list<Being *>::iterator i; - for (i = beings.begin(); i != beings.end(); i++) { - delete (*i); - } - beings.clear(); -} - void add_node(Being *being) { beings.push_back(being); } @@ -109,11 +101,11 @@ void sort() { } Being::Being(): - path(NULL), + speech_time(0), id(0), job(0), x(0), y(0), destX(0), destY(0), direction(0), type(0), action(0), frame(0), - speech(NULL), speech_time(0), speech_color(0), + speech_color(0), walk_time(0), speed(150), emotion(0), emotion_time(0), @@ -125,91 +117,64 @@ Being::Being(): Being::~Being() { clearPath(); - if (speech) { - free(speech); - } } void Being::clearPath() { - PATH_NODE *temp = path; - PATH_NODE *next; - while (temp) { - next = temp->next; - delete temp; - temp = next; - } - path = NULL; + path.clear(); } - -void Being::setPath(PATH_NODE *path) +void Being::setPath(std::list<PATH_NODE> path) { - clearPath(); this->path = path; - if (path != NULL) { - direction = 0; - if (path->next) { - if (path->next->x > path->x && path->next->y > path->y) - direction = SE; - else if (path->next->x < path->x && path->next->y > path->y) - direction = SW; - else if (path->next->x > path->x && path->next->y < path->y) - direction = NE; - else if (path->next->x < path->x && path->next->y < path->y) - direction = NW; - else if (path->next->x > path->x) - direction = EAST; - else if (path->next->x < path->x) - direction = WEST; - else if (path->next->y > path->y) - direction = SOUTH; - else if (path->next->y < path->y) - direction = NORTH; - } - PATH_NODE *pn = path; - this->path = path->next; - delete pn; - x = this->path->x; - y = this->path->y; - action = WALK; - walk_time = tick_time; - frame = 0; - } + nextStep(); } -bool Being::hasPath() +void Being::setHairColor(int color) { - return path != NULL; + hair_color = color; +} + +void Being::setHairStyle(int style) +{ + hair_style = style; +} + +void Being::setSpeech(const std::string &text, int time) +{ + speech = text; + speech_time = time; } void Being::nextStep() { - if (path && path->next) { - int old_x, old_y, new_x, new_y; - old_x = path->x; - old_y = path->y; - path = path->next; - new_x = path->x; - new_y = path->y; + if (!path.empty()) { + PATH_NODE node = path.front(); + path.pop_front(); + + int oldX = x; + int oldY = y; + int newX = node.x; + int newY = node.y; direction = 0; - if (new_x > old_x) { - if (new_y > old_y) direction = SE; - else if (new_y < old_y) direction = NE; + if (newX > oldX) { + if (newY > oldY) direction = SE; + else if (newY < oldY) direction = NE; else direction = EAST; } - else if (new_x < old_x) { - if (new_y > old_y) direction = SW; - else if (new_y < old_y) direction = NW; + else if (newX < oldX) { + if (newY > oldY) direction = SW; + else if (newY < oldY) direction = NW; else direction = WEST; } else { - if (new_y > old_y) direction = SOUTH; - else if (new_y < old_y) direction = NORTH; + if (newY > oldY) direction = SOUTH; + else if (newY < oldY) direction = NORTH; } - x = path->x; - y = path->y; + x = newX; + y = newY; + action = WALK; } else { action = STAND; if (this == player_node) { @@ -219,3 +184,27 @@ void Being::nextStep() frame = 0; walk_time = tick_time; } + +void Being::drawSpeech(Graphics *graphics) +{ + // Draw speech above this being + if (speech_time > 0) { + //if (being->speech_color == makecol(255, 255, 255)) { + // guiGraphics->drawText(being->speech, + // being->text_x + 16, being->text_y - 60, + // gcn::Graphics::CENTER); + //} + //else { + graphics->drawText(speech, + text_x + 60, text_y - 60, + gcn::Graphics::CENTER); + //} + } +} + +void Being::tick() +{ + if (speech_time > 0) { + speech_time--; + } +} diff --git a/src/being.h b/src/being.h index 657a0658..cc357ff3 100644 --- a/src/being.h +++ b/src/being.h @@ -25,6 +25,8 @@ #define _TMW_BEING_H #include <list> +#include <string> +#include "graphics.h" struct PATH_NODE { /** @@ -33,12 +35,13 @@ struct PATH_NODE { PATH_NODE(unsigned short x, unsigned short y); unsigned short x, y; - PATH_NODE *next; }; class Being { private: - PATH_NODE *path; + std::list<PATH_NODE> path; + std::string speech; + unsigned char speech_time; public: unsigned int id; @@ -49,8 +52,6 @@ class Being { unsigned char type; unsigned char action; unsigned char frame; - char *speech; - unsigned char speech_time; int speech_color; unsigned short walk_time; unsigned short speed; @@ -78,21 +79,44 @@ class Being { /** * Sets the new path for this being. */ - void setPath(PATH_NODE *path); + void setPath(std::list<PATH_NODE> path); + + /** + * Puts a "speech balloon" above this being for the specified amount + * of time. + * + * @param text The text that should appear. + * @param time The amount of time the text should stay in milliseconds. + */ + void setSpeech(const std::string &text, int time); + + /** + * Sets the hair color for this being. + */ + void setHairColor(int color); /** - * Returns wether this being has a path to follow. + * Sets the hair style for this being. */ - bool hasPath(); + void setHairStyle(int style); /** * Makes this being take the next step of his path. */ void nextStep(); -}; -/** Removes all beings from the list */ -void empty(); + /** + * Draws the speech text above the being. + */ + void drawSpeech(Graphics *graphics); + + /** + * Tick gives the being a sense of time. It should be called either a + * specific amount of times per second, or be modified to be passed a + * number that tells it the time since the last call. + */ + void tick(); +}; /** Add a Being to the list */ void add_node(Being *being); diff --git a/src/engine.cpp b/src/engine.cpp index 8ba4e7ea..36e6c212 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -407,10 +407,8 @@ void Engine::draw() being->frame = (get_elapsed_time(being->walk_time) * 4) / (being->speed); - if (being->frame >= 4) { - if (being->action != MONSTER_DEAD && being->hasPath()) { - being->nextStep(); - } + if (being->frame >= 4 && being->action != MONSTER_DEAD) { + being->nextStep(); } } } @@ -436,28 +434,26 @@ void Engine::draw() // purposes. if (displayPathToMouse) { - PATH_NODE *debugPath = tiledMap->findPath( + std::list<PATH_NODE> debugPath = tiledMap->findPath( player_node->x, player_node->y, mouseX / 32 + camera_x, mouseY / 32 + camera_y); - while (debugPath) + while (!debugPath.empty()) { - int squareX = (debugPath->x - camera_x) * 32 - offset_x + 12; - int squareY = (debugPath->y - camera_y) * 32 - offset_y + 12; + PATH_NODE node = debugPath.front(); + debugPath.pop_front(); + + int squareX = (node.x - camera_x) * 32 - offset_x + 12; + int squareY = (node.y - camera_y) * 32 - offset_y + 12; guiGraphics->setColor(gcn::Color(255, 0, 0)); guiGraphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8)); - MetaTile *tile = tiledMap->getMetaTile(debugPath->x, debugPath->y); + MetaTile *tile = tiledMap->getMetaTile(node.x, node.y); std::stringstream cost; cost << tile->Gcost; guiGraphics->drawText(cost.str(), squareX + 4, squareY + 12, gcn::Graphics::CENTER); - - // Move to the next node - PATH_NODE *temp = debugPath->next; - delete debugPath; - debugPath = temp; } } @@ -466,24 +462,10 @@ void Engine::draw() while (beingIterator != beings.end()) { Being *being = (*beingIterator); - if (being->speech != NULL) { - //if (being->speech_color == makecol(255, 255, 255)) { - // guiGraphics->drawText(being->speech, - // being->text_x + 16, being->text_y - 60, - // gcn::Graphics::CENTER); - //} - //else { - guiGraphics->drawText(being->speech, - being->text_x + 60, being->text_y - 60, - gcn::Graphics::CENTER); - //} - - being->speech_time--; - if (being->speech_time == 0) { - free(being->speech); - being->speech = NULL; - } - } + // Tick the beings (gives them a sense of time) + being->tick(); + + being->drawSpeech(guiGraphics); beingIterator++; } diff --git a/src/game.cpp b/src/game.cpp index 2342168e..f217f356 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -39,10 +39,11 @@ #include "resources/mapreader.h" #include "net/protocol.h" #include <SDL.h> +#include <sstream> char map_path[480]; -unsigned short dest_x, dest_y, src_x, src_y; +unsigned short src_x, src_y; bool refresh_beings = false; unsigned char keyb_state; volatile int tick_time; @@ -140,20 +141,20 @@ void do_init() SDL_AddTimer(1000, second, NULL); // Initialize beings - empty(); player_node = new Being(); player_node->id = account_ID; player_node->x = x; player_node->y = y; player_node->speed = 150; - player_node->hair_color = char_info->hair_color; - player_node->hair_style = char_info->hair_style; - std::cout << char_info->weapon << "\n"; + player_node->setHairColor(char_info->hair_color); + player_node->setHairStyle(char_info->hair_style); + if (char_info->weapon == 11) { char_info->weapon = 2; - std::cout << char_info->weapon << "\n"; } + player_node->weapon = char_info->weapon; + add_node(player_node); remove("./docs/packet.list"); @@ -505,38 +506,32 @@ void do_parse() { memcpy(temp, RFIFOP(8), RFIFOW(2)-8); being = find_node(RFIFOL(4)); if (being != NULL) { - if (being->speech != NULL) { - free(being->speech); - being->speech = NULL; - being->speech_time = 0; - } - being->speech = temp; - being->speech_time = SPEECH_TIME; - being->speech_color = 0;//makecol(255, 255, 255); - chatBox->chat_log(being->speech, BY_OTHER); + // White + being->setSpeech(temp, SPEECH_TIME); + chatBox->chat_log(temp, BY_OTHER); } + free(temp); break; case 0x008e: case 0x009a: if (RFIFOW(2) > 4) { - if(player_node->speech!=NULL) { - free(player_node->speech); - player_node->speech = NULL; - } - - player_node->speech = (char *)malloc(RFIFOW(2)-3); - memset(player_node->speech, '\0', RFIFOW(2)-3); - memcpy(player_node->speech, RFIFOP(4), RFIFOW(2)-4); // receive 1 byte less than expected, server might be sending garbage instead of '\0' /-kth5 + // Receiving 1 byte less than expected, server might be + // sending garbage instead of '\0' /-kth5 + temp = (char *)malloc(RFIFOW(2) - 3); + memset(temp, '\0', RFIFOW(2) - 3); + memcpy(temp, RFIFOP(4), RFIFOW(2) - 4); - player_node->speech_time = SPEECH_TIME; - player_node->speech_color = 0;//makecol(255, 255, 255); + // White + player_node->setSpeech(temp, SPEECH_TIME); if (id == 0x008e) { - chatBox->chat_log(player_node->speech, BY_PLAYER); + chatBox->chat_log(temp, BY_PLAYER); } else { - chatBox->chat_log(player_node->speech, BY_GM); + chatBox->chat_log(temp, BY_GM); } + + free(temp); } break; // Success to walk request @@ -562,8 +557,8 @@ void do_parse() { being->x = get_x(RFIFOP(46)); being->y = get_y(RFIFOP(46)); being->direction = get_direction(RFIFOP(46)); - being->hair_color = RFIFOW(28); - being->hair_style = RFIFOW(16); + being->setHairColor(RFIFOW(28)); + being->setHairStyle(RFIFOW(16)); add_node(being); } else { @@ -616,8 +611,8 @@ void do_parse() { being->walk_time = tick_time; being->frame = 0; being->speed = RFIFOW(6); - being->hair_color = RFIFOW(28); - being->hair_style = RFIFOW(16); + being->setHairColor(RFIFOW(28)); + being->setHairStyle(RFIFOW(16)); break; case SMSG_MOVE_BEING: @@ -660,8 +655,8 @@ void do_parse() { being->y = get_src_y(RFIFOP(50)); being->destX = get_dest_x(RFIFOP(50)); being->destY = get_dest_y(RFIFOP(50)); - being->hair_style = RFIFOW(16); - being->hair_color = RFIFOW(32); + being->setHairStyle(RFIFOW(16)); + being->setHairColor(RFIFOW(32)); being->setPath(tiledMap->findPath( being->x, being->y, @@ -734,26 +729,30 @@ void do_parse() { memset(map_path, '\0', 480); strcat(map_path, "./data/map/"); strncat(map_path, RFIFOP(2), 497 - strlen(map_path)); + log("Warping to %s (%d, %d)\n", + map_path, RFIFOW(18), RFIFOW(20)); + if (tiledMap) delete tiledMap; tiledMap = Map::load(map_path); + if (tiledMap) { - Being *temp; - temp = new Being(); - memcpy(temp, player_node, sizeof(Being)); - empty(); - /*player_node = new Being(); - player_node->job = 0; - player_node->action = STAND; - player_node->frame = 0; - player_node->speed = 150; - player_node->id = account_ID;*/ - add_node(temp); - player_node = temp; + // Delete all beings except the local player + std::list<Being *>::iterator i; + for (i = beings.begin(); i != beings.end(); i++) { + if ((*i) != player_node) { + delete (*i); + } + } + beings.clear(); + + // Re-add the local player node + add_node(player_node); + player_node->action = STAND; - current_npc = 0; player_node->frame = 0; player_node->x = RFIFOW(18); player_node->y = RFIFOW(20); + current_npc = 0; walk_status = 0; // Send "map loaded" WFIFOW(0) = net_w_value(0x007d); @@ -828,8 +827,7 @@ void do_parse() { deathNotice = new OkDialog("Message", "You're now dead, press ok to restart", &deathNoticeListener); - //remove_node(char_info->id); - being->action = DEAD; + player_node->action = DEAD; } break; // Stop walking @@ -851,26 +849,17 @@ void do_parse() { case 0: // Damage being = find_node(RFIFOL(6)); if (being != NULL) { - if (being->speech != NULL) { - free(being->speech); - being->speech = NULL; - //being->speech_time = SPEECH_TIME; - } - being->speech = (char *)malloc(5); - memset(being->speech, '\0', 5); + if (RFIFOW(22) == 0) { - sprintf(being->speech, "miss"); - being->speech_color = 0;//makecol(255, 255, 0); + // Yellow + being->setSpeech("miss", SPEECH_TIME); } else { - sprintf(being->speech, "%i", RFIFOW(22)); - if (being->id != player_node->id) { - being->speech_color = 0;//makecol(0,0,255); - } - else { - being->speech_color = 0;//makecol(255,0,0); - } + // Blue for monster, red for player + std::stringstream ss; + ss << RFIFOW(22); + being->setSpeech(ss.str(), SPEECH_TIME); } - being->speech_time = SPEECH_TIME; + if (RFIFOL(2) != player_node->id) { // buggy being = find_node(RFIFOL(2)); if (being != NULL) { @@ -1122,17 +1111,18 @@ void do_parse() { npcListDialog->parseItems(RFIFOP(8)); npcListDialog->setVisible(true); break; - // Look change - case 0x00c3: - // Change hair color - if (RFIFOB(6) == 6) { - being = find_node(RFIFOL(2)); - being->hair_color = RFIFOB(7); - } else if (RFIFOB(6) == 1) { - being = find_node(RFIFOL(2)); - being->hair_style = RFIFOB(7); + + case SMSG_CHANGE_BEING_LOOKS: + being = find_node(RFIFOL(2)); + if (being) { + if (RFIFOB(6) == 6) { + being->setHairColor(RFIFOB(7)); + } else if (RFIFOB(6) == 1) { + being->setHairStyle(RFIFOB(7)); + } } break; + // Answer to equip item case 0x00aa: if (RFIFOB(6) == 0) @@ -1162,7 +1152,7 @@ void do_parse() { // Trick to use the proper graphic until I find // the right packet - switch(inventoryWindow->items->getId(RFIFOW(2))) { + switch (inventoryWindow->items->getId(RFIFOW(2))) { case 1201: player_node->weapon = 1; break; @@ -1299,7 +1289,6 @@ void do_parse() { // Manage non implemented packets default: log("Unhandled packet: %x", id); - //alert(pkt_nfo,"","","","",0,0); break; } diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index 4f71e94d..2f1fc36b 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -223,7 +223,7 @@ void Setup::action(const std::string &eventId) // Sound settings if (soundCheckBox->isMarked()) { - config.setValue("sound",1); + config.setValue("sound", 1); try { sound.init(32, 20); } diff --git a/src/main.cpp b/src/main.cpp index 69ffd431..a48b184b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,20 +76,6 @@ Sound sound; // ini file configuration reader Configuration config; -// macros for safe object deletion -#define SAFE_DELETE(object) { \ - if (object != NULL) { \ - delete object; \ - } \ -} - -#define SAFE_DELETE_ARRAY(array) { \ - if (array != NULL) { \ - delete [] array; \ - } \ -} - - /** * Listener used for responding to map start error dialog. */ @@ -313,9 +299,9 @@ void init_engine() void exit_engine() { config.write(dir); - SAFE_DELETE_ARRAY(dir); - SAFE_DELETE(gui); - SAFE_DELETE(graphics); + delete[] dir; + delete gui; + delete graphics; // Shutdown libxml xmlCleanupParser(); diff --git a/src/map.cpp b/src/map.cpp index d4fb9dde..9419233d 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -272,13 +272,17 @@ int Map::getTileHeight() return tileHeight; } -PATH_NODE *Map::findPath(int startX, int startY, int destX, int destY) +std::list<PATH_NODE> Map::findPath( + int startX, int startY, int destX, int destY) { + // Path to be built up (empty by default) + std::list<PATH_NODE> path; + // Declare open list, a list with open tiles sorted on F cost std::priority_queue<Location> openList; // Return when destination not walkable - if (!getWalk(destX, destY)) return NULL; + if (!getWalk(destX, destY)) return path; // Reset starting tile's G cost to 0 MetaTile *startTile = getMetaTile(startX, startY); @@ -402,26 +406,20 @@ PATH_NODE *Map::findPath(int startX, int startY, int destX, int destY) // to extract it. if (foundPath) { - PATH_NODE *path = new PATH_NODE(destX, destY); int pathX = destX; int pathY = destY; while (pathX != startX || pathY != startY) { + // Add the new path node to the start of the path list + path.push_front(PATH_NODE(pathX, pathY)); + // Find out the next parent MetaTile *tile = getMetaTile(pathX, pathY); pathX = tile->parentX; pathY = tile->parentY; - - // Add the new path node to the start of the path list - PATH_NODE *pn = new PATH_NODE(pathX, pathY); - pn->next = path; - path = pn; } - - return path; } - // No path found - return NULL; + return path; } @@ -27,6 +27,7 @@ #include "being.h" #include "graphics.h" #include "resources/image.h" +#include <list> /** * A meta tile stores additional information about a location on a tile map. @@ -155,7 +156,8 @@ class Map /** * Find a path from one location to the next. */ - PATH_NODE *findPath(int startX, int startY, int destX, int destY); + std::list<PATH_NODE> findPath( + int startX, int startY, int destX, int destY); private: int width, height; diff --git a/src/net/protocol.h b/src/net/protocol.h index 2f4911d5..ea746412 100644 --- a/src/net/protocol.h +++ b/src/net/protocol.h @@ -31,7 +31,7 @@ #define SMSG_PLAYER_UPDATE_1 0x01d8 // #define SMSG_PLAYER_UPDATE_2 0x01d9 // #define SMSG_MOVE_PLAYER_BEING 0x01da // A nearby player moves - +#define SMSG_CHANGE_BEING_LOOKS 0x00c3 // /** Packet length by id */ diff --git a/src/sound.cpp b/src/sound.cpp index 20530750..6e2c19fe 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -30,9 +30,8 @@ void Sound::init(int voices, int mod_voices) { - if (isOk == 0) { - throw("Sound engine cannot be initialized twice!\n"); - } + // Don't initialize sound engine twice + if (isOk == 0) return; bgm = NULL; int audio_rate = 44100; |