diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game-server/actor.h | 18 | ||||
-rw-r--r-- | src/game-server/being.cpp | 2 | ||||
-rw-r--r-- | src/game-server/character.cpp | 4 | ||||
-rw-r--r-- | src/game-server/character.h | 7 | ||||
-rw-r--r-- | src/game-server/component.h | 5 | ||||
-rw-r--r-- | src/game-server/gamehandler.cpp | 13 | ||||
-rw-r--r-- | src/game-server/monster.cpp | 1 | ||||
-rw-r--r-- | src/game-server/monster.h | 7 | ||||
-rw-r--r-- | src/game-server/npc.cpp | 123 | ||||
-rw-r--r-- | src/game-server/npc.h | 83 | ||||
-rw-r--r-- | src/game-server/state.cpp | 10 | ||||
-rw-r--r-- | src/scripting/lua.cpp | 64 | ||||
-rw-r--r-- | src/scripting/luautil.cpp | 8 | ||||
-rw-r--r-- | src/scripting/luautil.h | 5 |
14 files changed, 178 insertions, 172 deletions
diff --git a/src/game-server/actor.h b/src/game-server/actor.h index 13d4af55..83b2c0fe 100644 --- a/src/game-server/actor.h +++ b/src/game-server/actor.h @@ -54,7 +54,8 @@ class Actor : public Entity mUpdateFlags(0), mPublicID(65535), mSize(0), - mWalkMask(0) + mWalkMask(0), + mBlockType(BLOCKTYPE_NONE) {} ~Actor(); @@ -126,16 +127,20 @@ class Actor : public Entity { return mWalkMask; } /** + * Gets the way the actor blocks pathfinding for other actors. + */ + BlockType getBlockType() const + { return mBlockType; } + + void setBlockType(BlockType blockType) + { mBlockType = blockType; } + + /** * Overridden in order to update the walkmap. */ virtual void setMap(MapComposite *map); protected: - /** - * Gets the way the actor blocks pathfinding for other actors. - */ - virtual BlockType getBlockType() const - { return BLOCKTYPE_NONE; } /** Delay until move to next tile in miliseconds. */ unsigned short mMoveTime; @@ -150,6 +155,7 @@ class Actor : public Entity unsigned char mSize; /**< Radius of bounding circle. */ unsigned char mWalkMask; + BlockType mBlockType; }; #endif // ACTOR_H diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index 66545ff6..9112a1b8 100644 --- a/src/game-server/being.cpp +++ b/src/game-server/being.cpp @@ -743,6 +743,8 @@ void Being::update() died(); processAttacks(); + + Actor::update(); } void Being::inserted(Entity *) diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp index b139f121..8cc0e65a 100644 --- a/src/game-server/character.cpp +++ b/src/game-server/character.cpp @@ -97,6 +97,7 @@ Character::Character(MessageIn &msg): mAttributes.insert(std::make_pair(it1->first, Attribute(*it1->second))); setWalkMask(Map::BLOCKMASK_WALL); + setBlockType(BLOCKTYPE_CHARACTER); // Get character data. mDatabaseID = msg.readInt32(); @@ -677,6 +678,9 @@ AttribmodResponseCode Character::useCorrectionPoint(size_t attribute) void Character::startNpcThread(Script::Thread *thread, int npcId) { + if (mNpcThread) + delete mNpcThread; + mNpcThread = thread; mTalkNpcId = npcId; diff --git a/src/game-server/character.h b/src/game-server/character.h index 2b755bdb..dc703c8f 100644 --- a/src/game-server/character.h +++ b/src/game-server/character.h @@ -431,13 +431,6 @@ class Character : public Being sigc::signal<void, Character *> signal_disconnected; - protected: - /** - * Gets the way the actor blocks pathfinding for other objects - */ - virtual BlockType getBlockType() const - { return BLOCKTYPE_CHARACTER; } - private: bool specialUseCheck(SpecialMap::iterator it); diff --git a/src/game-server/component.h b/src/game-server/component.h index 90dda5a5..740668a8 100644 --- a/src/game-server/component.h +++ b/src/game-server/component.h @@ -26,9 +26,10 @@ class Entity; enum ComponentType { CT_Effect, - CT_TriggerArea, - CT_SpawnArea, CT_Item, + CT_Npc, + CT_SpawnArea, + CT_TriggerArea, ComponentTypeCount }; diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index eeccdcc5..51b64a26 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -453,22 +453,25 @@ void GameHandler::handleNpc(GameClient &client, MessageIn &message) return; } - NPC *npc = static_cast<NPC *>(actor); + Being *npc = static_cast<Being*>(actor); + switch (message.getId()) { case PGMSG_NPC_SELECT: - npc->select(client.character, message.readInt8()); + Npc::integerReceived(client.character, message.readInt8()); break; case PGMSG_NPC_NUMBER: - npc->integerReceived(client.character, message.readInt32()); + Npc::integerReceived(client.character, message.readInt32()); break; case PGMSG_NPC_STRING: - npc->stringReceived(client.character, message.readString()); + Npc::stringReceived(client.character, message.readString()); break; case PGMSG_NPC_TALK: + Npc::start(npc, client.character); + break; case PGMSG_NPC_TALK_NEXT: default: - npc->prompt(client.character, message.getId() == PGMSG_NPC_TALK); + Npc::resume(client.character); break; } } diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index edc89ec1..ceae82ca 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -60,6 +60,7 @@ Monster::Monster(MonsterClass *specy): LOG_DEBUG("Monster spawned! (id: " << mSpecy->getId() << ")."); setWalkMask(Map::BLOCKMASK_WALL | Map::BLOCKMASK_CHARACTER); + setBlockType(BLOCKTYPE_MONSTER); /* * Initialise the attribute structures. diff --git a/src/game-server/monster.h b/src/game-server/monster.h index 8e927f92..e87180dd 100644 --- a/src/game-server/monster.h +++ b/src/game-server/monster.h @@ -318,13 +318,6 @@ class Monster : public Being */ void forgetTarget(Entity *entity); - protected: - /** - * Returns the way the actor blocks pathfinding for other objects. - */ - virtual BlockType getBlockType() const - { return BLOCKTYPE_MONSTER; } - private: static const int DECAY_TIME = 50; diff --git a/src/game-server/npc.cpp b/src/game-server/npc.cpp index 2eb73031..788f0c95 100644 --- a/src/game-server/npc.cpp +++ b/src/game-server/npc.cpp @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2007-2010 The Mana World Development Team + * Copyright (C) 2012 The Mana Developers * * This file is part of The Mana Server. * @@ -18,127 +19,109 @@ * along with The Mana Server. If not, see <http://www.gnu.org/licenses/>. */ +#include "game-server/npc.h" + #include "game-server/character.h" #include "game-server/gamehandler.h" #include "game-server/map.h" -#include "game-server/npc.h" #include "net/messageout.h" #include "scripting/script.h" #include "scripting/scriptmanager.h" -NPC::NPC(const std::string &name, int id): - Being(OBJECT_NPC), - mID(id), +const ComponentType NpcComponent::type; + +NpcComponent::NpcComponent(int npcId): + mNpcId(npcId), mEnabled(true) { - setWalkMask(Map::BLOCKMASK_WALL | Map::BLOCKMASK_MONSTER | - Map::BLOCKMASK_CHARACTER); - setName(name); } -NPC::~NPC() +NpcComponent::~NpcComponent() { Script *script = ScriptManager::currentState(); script->unref(mTalkCallback); script->unref(mUpdateCallback); } -void NPC::setEnabled(bool enabled) +void NpcComponent::setEnabled(bool enabled) { mEnabled = enabled; } -void NPC::update() +void NpcComponent::update(Entity &entity) { if (!mEnabled || !mUpdateCallback.isValid()) return; Script *script = ScriptManager::currentState(); script->prepare(mUpdateCallback); - script->push(this); - script->execute(getMap()); + script->push(&entity); + script->execute(entity.getMap()); } -void NPC::prompt(Character *ch, bool restart) +void NpcComponent::setTalkCallback(Script::Ref function) { - if (!mEnabled || !mTalkCallback.isValid()) - return; + ScriptManager::currentState()->unref(mTalkCallback); + mTalkCallback = function; +} - Script *script = ScriptManager::currentState(); +void NpcComponent::setUpdateCallback(Script::Ref function) +{ + ScriptManager::currentState()->unref(mUpdateCallback); + mUpdateCallback = function; +} - if (restart) - { - Script::Thread *thread = script->newThread(); - thread->getContext().map = getMap(); - script->prepare(mTalkCallback); - script->push(this); - script->push(ch); - ch->startNpcThread(thread, getPublicID()); - } - else - { - Script::Thread *thread = ch->getNpcThread(); - if (!thread || thread->mState != Script::ThreadPaused) - return; - script->prepareResume(thread); - ch->resumeNpcThread(); - } -} -void NPC::select(Character *ch, int index) +static Script *prepareResume(Character *ch, Script::ThreadState expectedState) { - if (!mEnabled) - return; - Script::Thread *thread = ch->getNpcThread(); - if (!thread || thread->mState != Script::ThreadExpectingNumber) - return; + if (!thread || thread->mState != expectedState) + return 0; Script *script = ScriptManager::currentState(); script->prepareResume(thread); - script->push(index); - ch->resumeNpcThread(); + return script; } -void NPC::integerReceived(Character *ch, int value) +void Npc::start(Being *npc, Character *ch) { - if (!mEnabled) - return; - - Script::Thread *thread = ch->getNpcThread(); - if (!thread || thread->mState != Script::ThreadExpectingNumber) - return; + NpcComponent *npcComponent = npc->getComponent<NpcComponent>(); Script *script = ScriptManager::currentState(); - script->prepareResume(thread); - script->push(value); - ch->resumeNpcThread(); + Script::Ref talkCallback = npcComponent->getTalkCallback(); + + if (npcComponent->isEnabled() && talkCallback.isValid()) + { + Script::Thread *thread = script->newThread(); + thread->getContext().map = npc->getMap(); + script->prepare(talkCallback); + script->push(npc); + script->push(ch); + ch->startNpcThread(thread, npc->getPublicID()); + } } -void NPC::stringReceived(Character *ch, const std::string &value) +void Npc::resume(Character *ch) { - if (!mEnabled) - return; - - Script::Thread *thread = ch->getNpcThread(); - if (!thread || thread->mState != Script::ThreadExpectingString) - return; - - Script *script = ScriptManager::currentState(); - script->prepareResume(thread); - script->push(value); - ch->resumeNpcThread(); + if (prepareResume(ch, Script::ThreadPaused)) + ch->resumeNpcThread(); } -void NPC::setTalkCallback(Script::Ref function) +void Npc::integerReceived(Character *ch, int value) { - ScriptManager::currentState()->unref(mTalkCallback); - mTalkCallback = function; + if (Script *script = prepareResume(ch, Script::ThreadExpectingNumber)) + { + script->push(value); + ch->resumeNpcThread(); + } } -void NPC::setUpdateCallback(Script::Ref function) +void Npc::stringReceived(Character *ch, const std::string &value) { - ScriptManager::currentState()->unref(mUpdateCallback); - mUpdateCallback = function; + if (Script *script = prepareResume(ch, Script::ThreadExpectingString)) + { + script->push(value); + ch->resumeNpcThread(); + } } diff --git a/src/game-server/npc.h b/src/game-server/npc.h index 49dd4bfa..1a0b4e8e 100644 --- a/src/game-server/npc.h +++ b/src/game-server/npc.h @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2007-2010 The Mana World Development Team + * Copyright (C) 2012 The Mana Developers * * This file is part of The Mana Server. * @@ -21,26 +22,31 @@ #ifndef GAMESERVER_NPC_H #define GAMESERVER_NPC_H -#include "game-server/being.h" +#include "game-server/component.h" #include "scripting/script.h" class Character; /** - * Class describing a non-player character. + * Component describing a non-player character. */ -class NPC : public Being +class NpcComponent : public Component { public: - NPC(const std::string &name, int id); + static const ComponentType type = CT_Npc; - ~NPC(); + NpcComponent(int npcId); + + ~NpcComponent(); /** * Sets the function that should be called when this NPC is talked to. */ void setTalkCallback(Script::Ref function); + Script::Ref getTalkCallback() const + { return mTalkCallback; } + /** * Sets the function that should be called each update. */ @@ -49,52 +55,57 @@ class NPC : public Being /** * Calls the update callback, if any. */ - void update(); + void update(Entity &entity); /** * Sets whether the NPC is enabled. + * + * When disabling an NPC, it does currently not cancel already started + * conversations with this NPC! */ void setEnabled(bool enabled); - /** - * Prompts NPC. - */ - void prompt(Character *, bool restart); - - /** - * Selects an NPC proposition. - */ - void select(Character *, int index); - - /** - * The player has choosen an integer. - */ - void integerReceived(Character *ch, int value); - - /** - * The player has entered an string. - */ - void stringReceived(Character *ch, const std::string &value); + bool isEnabled() const + { return mEnabled; } /** * Gets NPC ID. */ - int getNPC() const - { return mID; } - - protected: - /** - * Gets the way a monster blocks pathfinding for other objects - */ - virtual BlockType getBlockType() const - { return BLOCKTYPE_CHARACTER; } // blocks like a player character + int getNpcId() const + { return mNpcId; } private: - unsigned short mID; /**< ID of the NPC. */ - bool mEnabled; /**< Whether NPC is enabled */ + int mNpcId; + bool mEnabled; Script::Ref mTalkCallback; Script::Ref mUpdateCallback; }; + +namespace Npc { + +/** + * Starts a conversation with the NPC. + */ +void start(Being *npc, Character *ch); + +/** + * Resumes an NPC conversation. + */ +void resume(Character *ch); + +/** + * The player has made a choice or entered an integer. + */ +void integerReceived(Character *ch, int value); + +/** + * The player has entered an string. + */ +void stringReceived(Character *ch, const std::string &value); + +} // namespace Npc + + #endif // GAMESERVER_NPC_H diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index ab0dcd79..673d48fa 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -274,9 +274,9 @@ static void informPlayer(MapComposite *map, Character *p) case OBJECT_NPC: { - NPC *q = static_cast< NPC * >(o); - enterMsg.writeInt16(q->getNPC()); - enterMsg.writeString(q->getName()); + NpcComponent *npcComponent = o->getComponent<NpcComponent>(); + enterMsg.writeInt16(npcComponent->getNpcId()); + enterMsg.writeString(o->getName()); } break; default: @@ -550,7 +550,7 @@ bool GameState::insert(Entity *ptr) break; case OBJECT_NPC: - LOG_DEBUG("NPC inserted: " << static_cast<NPC*>(obj)->getNPC()); + LOG_DEBUG("NPC inserted: " << obj->getComponent<NpcComponent>()->getNpcId()); break; case OBJECT_CHARACTER: @@ -624,7 +624,7 @@ void GameState::remove(Entity *ptr) break; case OBJECT_NPC: - LOG_DEBUG("NPC removed: " << static_cast<NPC*>(ptr)->getNPC()); + LOG_DEBUG("NPC removed: " << ptr->getComponent<NpcComponent>()->getNpcId()); break; case OBJECT_CHARACTER: diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 705ee4c9..d4438990 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -280,25 +280,35 @@ static int npc_create(lua_State *s) MapComposite *m = checkCurrentMap(s); - NPC *q = new NPC(name, id); - q->setGender(getGender(gender)); - q->setMap(m); - q->setPosition(Point(x, y)); + NpcComponent *npcComponent = new NpcComponent(id); + + Being *npc = new Being(OBJECT_NPC); + npc->addComponent(npcComponent); + // some health so it doesn't spawn dead + npc->setAttribute(ATTR_MAX_HP, 100); + npc->setAttribute(ATTR_HP, 100); + npc->setName(name); + npc->setGender(getGender(gender)); + + npc->setWalkMask(Map::BLOCKMASK_WALL | Map::BLOCKMASK_MONSTER | + Map::BLOCKMASK_CHARACTER); + npc->setMap(m); + npc->setPosition(Point(x, y)); if (lua_isfunction(s, 6)) { lua_pushvalue(s, 6); - q->setTalkCallback(luaL_ref(s, LUA_REGISTRYINDEX)); + npcComponent->setTalkCallback(luaL_ref(s, LUA_REGISTRYINDEX)); } if (lua_isfunction(s, 7)) { lua_pushvalue(s, 7); - q->setUpdateCallback(luaL_ref(s, LUA_REGISTRYINDEX)); + npcComponent->setUpdateCallback(luaL_ref(s, LUA_REGISTRYINDEX)); } - GameState::enqueueInsert(q); - lua_pushlightuserdata(s, q); + GameState::enqueueInsert(npc); + lua_pushlightuserdata(s, npc); return 1; } @@ -309,9 +319,9 @@ static int npc_create(lua_State *s) */ static int npc_enable(lua_State *s) { - NPC *p = checkNPC(s, 1); - p->setEnabled(true); - GameState::enqueueInsert(p); + Being *npc = checkNpc(s, 1); + npc->getComponent<NpcComponent>()->setEnabled(true); + GameState::enqueueInsert(npc); return 0; } @@ -322,9 +332,9 @@ static int npc_enable(lua_State *s) */ static int npc_disable(lua_State *s) { - NPC *p = checkNPC(s, 1); - p->setEnabled(false); - GameState::remove(p); + Being *npc = checkNpc(s, 1); + npc->getComponent<NpcComponent>()->setEnabled(false); + GameState::remove(npc); return 0; } @@ -489,14 +499,14 @@ static int item_drop(lua_State *s) */ static int npc_message(lua_State *s) { - NPC *p = checkNPC(s, 1); + Being *npc = checkNpc(s, 1); Character *q = checkCharacter(s, 2); const char *m = luaL_checkstring(s, 3); Script::Thread *thread = checkCurrentThread(s); MessageOut msg(GPMSG_NPC_MESSAGE); - msg.writeInt16(p->getPublicID()); + msg.writeInt16(npc->getPublicID()); msg.writeString(m); gameHandler->sendTo(q, msg); @@ -522,13 +532,13 @@ static int npc_message(lua_State *s) */ static int npc_choice(lua_State *s) { - NPC *p = checkNPC(s, 1); + Being *npc = checkNpc(s, 1); Character *q = checkCharacter(s, 2); Script::Thread *thread = checkCurrentThread(s); MessageOut msg(GPMSG_NPC_CHOICE); - msg.writeInt16(p->getPublicID()); + msg.writeInt16(npc->getPublicID()); for (int i = 3, i_end = lua_gettop(s); i <= i_end; ++i) { if (lua_isstring(s, i)) @@ -578,7 +588,7 @@ static int npc_choice(lua_State *s) */ static int npc_ask_integer(lua_State *s) { - NPC *p = checkNPC(s, 1); + Being *npc = checkNpc(s, 1); Character *q = checkCharacter(s, 2); int min = luaL_checkint(s, 3); int max = luaL_checkint(s, 4); @@ -587,7 +597,7 @@ static int npc_ask_integer(lua_State *s) Script::Thread *thread = checkCurrentThread(s); MessageOut msg(GPMSG_NPC_NUMBER); - msg.writeInt16(p->getPublicID()); + msg.writeInt16(npc->getPublicID()); msg.writeInt32(min); msg.writeInt32(max); msg.writeInt32(defaultValue); @@ -608,13 +618,13 @@ static int npc_ask_integer(lua_State *s) */ static int npc_ask_string(lua_State *s) { - NPC *p = checkNPC(s, 1); + Being *npc = checkNpc(s, 1); Character *q = checkCharacter(s, 2); Script::Thread *thread = checkCurrentThread(s); MessageOut msg(GPMSG_NPC_STRING); - msg.writeInt16(p->getPublicID()); + msg.writeInt16(npc->getPublicID()); gameHandler->sendTo(q, msg); thread->mState = Script::ThreadExpectingString; @@ -628,11 +638,11 @@ static int npc_ask_string(lua_State *s) */ static int npc_post(lua_State *s) { - NPC *p = checkNPC(s, 1); + Being *npc = checkNpc(s, 1); Character *q = checkCharacter(s, 2); MessageOut msg(GPMSG_NPC_POST); - msg.writeInt16(p->getPublicID()); + msg.writeInt16(npc->getPublicID()); gameHandler->sendTo(q, msg); return 0; @@ -755,7 +765,7 @@ static int announce(lua_State *s) */ static int npc_trade(lua_State *s) { - NPC *p = checkNPC(s, 1); + Being *npc = checkNpc(s, 1); Character *q = checkCharacter(s, 2); if (!lua_isboolean(s, 3)) { @@ -778,7 +788,7 @@ static int npc_trade(lua_State *s) return 1; } - if (t->start(p)) + if (t->start(npc)) { lua_pushinteger(s, 0); return 1; @@ -856,7 +866,7 @@ static int npc_trade(lua_State *s) lua_pushinteger(s, 1); return 1; } - if (t->start(p)) + if (t->start(npc)) { lua_pushinteger(s, 0); return 1; diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp index 6210eda0..24e9edf7 100644 --- a/src/scripting/luautil.cpp +++ b/src/scripting/luautil.cpp @@ -188,14 +188,14 @@ MonsterClass *getMonsterClass(lua_State *s, int p) return monsterClass; } -NPC *getNPC(lua_State *s, int p) +Being *getNpc(lua_State *s, int p) { if (!lua_islightuserdata(s, p)) return 0; Entity *t = static_cast<Entity *>(lua_touserdata(s, p)); if (t->getType() != OBJECT_NPC) return 0; - return static_cast<NPC *>(t); + return static_cast<Being*>(t); } @@ -234,9 +234,9 @@ MonsterClass *checkMonsterClass(lua_State *s, int p) return monsterClass; } -NPC *checkNPC(lua_State *s, int p) +Being *checkNpc(lua_State *s, int p) { - NPC *npc = getNPC(s, p); + Being *npc = getNpc(s, p); luaL_argcheck(s, npc, p, "npc expected"); return npc; } diff --git a/src/scripting/luautil.h b/src/scripting/luautil.h index 8e380d4e..dd63c0f7 100644 --- a/src/scripting/luautil.h +++ b/src/scripting/luautil.h @@ -45,7 +45,6 @@ class MapComposite; class MapObject; class Monster; class MonsterClass; -class NPC; class StatusEffect; void raiseWarning(lua_State *s, const char *format, ...); @@ -172,14 +171,14 @@ Character * getCharacter(lua_State *s, int p); ItemClass * getItemClass(lua_State *s, int p); Monster * getMonster(lua_State *s, int p); MonsterClass * getMonsterClass(lua_State *s, int p); -NPC * getNPC(lua_State *s, int p); +Being * getNpc(lua_State *s, int p); Being * checkBeing(lua_State *s, int p); Character * checkCharacter(lua_State *s, int p); ItemClass * checkItemClass(lua_State *s, int p); Monster * checkMonster(lua_State *s, int p); MonsterClass * checkMonsterClass(lua_State *s, int p); -NPC * checkNPC(lua_State *s, int p); +Being * checkNpc(lua_State *s, int p); int checkSkill(lua_State *s, int p); int checkSpecial(lua_State *s, int p); |