diff --git a/data/XML/stages.xml b/data/XML/stages.xml index 6895898..aae0474 100644 --- a/data/XML/stages.xml +++ b/data/XML/stages.xml @@ -1,6 +1,6 @@ - + diff --git a/data/events/scripts/player.lua b/data/events/scripts/player.lua index 9d0f656..9e302d9 100644 --- a/data/events/scripts/player.lua +++ b/data/events/scripts/player.lua @@ -175,7 +175,9 @@ function Player:onGainExperience(source, exp, rawExp) end -- Apply experience stage multiplier - exp = exp * Game.getExperienceStage(self:getLevel()) + if (vocation:getId() > 0 or self:getLevel() < 8) then + exp = exp * Game.getExperienceStage(self:getLevel()) + end -- Stamina modifier if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then diff --git a/data/npc/amber.npc b/data/npc/amber.npc index 0ebf472..da1f946 100644 --- a/data/npc/amber.npc +++ b/data/npc/amber.npc @@ -67,4 +67,27 @@ Topic=2,"no" -> "In orcish that's 'burp'. I help you more about that if you hav Topic=3,"yes",Count(Type)>=Amount -> "Thank you. Orcs call arrows 'pixo'.", Delete(Type) Topic=3,"yes" -> "You don't have one!" Topic=3 -> "Ok, then I don't tell you more about the orcish language." + +"addon",QuestValue(18502)=0,premium -> "Ah, you noticed my new accessory? Sorry, this one is not for sale. It's handmade from rare minotaur leather.", Topic=4 +"backpack",QuestValue(18502)=0,premium -> * +"addon",QuestValue(18502)=0 -> "Ah, you noticed my new accessory? Sorry, this one is not for sale." +"backpack",QuestValue(18502)=0 -> * +Topic=4,"minotaur","leather" -> "Well, if you really like this backpack, I could make one for you, but minotaur leather is hard to come by these days. Are you willing to put some work into this?", Topic=5 +Topic=5,"yes" -> "Alright then, if you bring me 100 pieces of fine minotaur leather I will see what I can do for you. You probably have to kill really many minotaurs though...", + "so good luck!", SetQuestValue(18502,1) + +"addon",QuestValue(18502)=1 -> Type=5878, Amount=100, "Ah, right, almost forgot about the backpack! Have you brought me 100 pieces of minotaur leather as requested?", Topic=6 +"backpack",QuestValue(18502)=1 -> * +Topic=6,"yes",Count(Type)>=Amount -> "Great! Alright, I need a while to finish this backpack for you. Come ask me later, okay?", Delete(Type), SetExpiringQuestValue(18503, 7200000), SetQuestValue(18502,2) +Topic=6,"yes" -> "You don't have that many!" +Topic=6 -> "Too bad." + +"addon",ExpiringQuestValue(18503)>0 -> "Please be patient! I am still working on the backpack details. Come back later, okey?" +"backpack",ExpiringQuestValue(18503)>0 -> * + +"addon",ExpiringQuestValue(18503)<0,QuestValue(18502)=2 -> "Just in time! Your backpack is finished. Here you go, I hope you like it.", SetQuestValue(18502,3), AddOutfitAddon(136,1), AddOutfitAddon(128,1) +"backpack",ExpiringQuestValue(18503)<0,QuestValue(18502)=2 -> * + +"addon",QuestValue(18502)=3 -> "Oh, you also have a nice backpack just like me!" +"backpack",QuestValue(18502)=3 -> * } diff --git a/data/npc/norma.npc b/data/npc/norma.npc index bf1f9cb..03c1318 100644 --- a/data/npc/norma.npc +++ b/data/npc/norma.npc @@ -2,7 +2,7 @@ # norma.npc: Datenbank für die Händlerin Norma (Newbie) Name = "Norma" -Outfit = (136,78-76-72-96) +Outfit = (136,78-76-72-96-2) Home = [32098,32180,7] Radius = 2 @@ -166,4 +166,19 @@ Topic=2,"yes",Count(Type)>=Amount -> "Ok. Here is your money.", Delete(Type), Cr Topic=2,"yes" -> "Sorry, you do not have one." Topic=2,"yes",Amount>1 -> "Sorry, you do not have that many." Topic=2 -> "Maybe next time." + +"addon",QuestValue(18501)=0 -> "Pretty, isn't it? I made it myself, but I could teach you how to do that if you like. What do you say?", Topic=3 +"hat",QuestValue(18501)=0 -> * +Topic=3,"yes" -> "Okay, here we go, listen closely! I need a few things... a basic hat of course, maybe a legion helmet would do. Then about 100 chicken feathers...", + "and 50 honeycombs as glue. That's it, come back to me once you gathered it!", SetQuestValue(18501,1) +Topic=3 -> "Maybe another time." + +"addon",QuestValue(18501)=1 -> "Oh, you're back already? Did you bring a legion helmet, 100 chicken feathers and 50 honeycombs?", Topic=4 +"hat",QuestValue(18501)=1 -> * +Topic=4,"yes",Count(3374)>=1,Count(5890)>=100,Count(5902)>=50 -> "Great job! That must have taken a lot of work. Okay, you put it like this... then glue like this... here!", DeleteAmount(3374,1), DeleteAmount(5890,100), DeleteAmount(5902,50), SetQuestValue(18501,2), AddOutfitAddon(136,2), AddOutfitAddon(128,2) +Topic=4,"yes" -> "You don't have required ingredients." +Topic=4 -> "Maybe another time." + +"addon",QuestValue(18501)>1 -> "I hope you enjoy the hat!" +"hat",QuestValue(18501)>1 -> * } diff --git a/data/npc/tom.npc b/data/npc/tom.npc index a397d1a..2c68c77 100644 --- a/data/npc/tom.npc +++ b/data/npc/tom.npc @@ -2,7 +2,7 @@ # tom.npc: Datenbank fuer den Gerber Tom Name = "Tom" -Outfit = (129,113-115-58-115) +Outfit = (144,113-115-58-115-1) Home = [32085,32199,7] Radius = 1 @@ -64,4 +64,20 @@ Topic=2,"yes",Amount>1 -> "Sorry, you do not have so many." Topic=2 -> "Maybe another time." "sell" -> "Sorry. I'm only selling to major customers. But I'm buying fresh corpses of rats, rabbits and wolves from you." + + +"addon",QuestValue(18504)=0,premium -> "Would you like to wear bear paws like I do? No problem, just bring me 50 bear paws and 50 wolf paws and I'll fit them on.", SetQuestValue(18504,1) +"paws",QuestValue(18504)=0,premium -> * +"addon",QuestValue(18504)=0 -> "Addons can be wear only by premium players." +"paws",QuestValue(18504)=0 -> * + +"addon",QuestValue(18504)=1 -> "Have you brought 50 bear paws and 50 wolf paws?", Topic=3 +"paws",QuestValue(18504)=1 -> * +Topic=3,"yes",Count(5897)>=50,Count(5896)>=50 -> "Excellent! Like promised, here are your bear paws.", DeleteAmount(5897,50), DeleteAmount(5896,50), SetQuestValue(18504,2), AddOutfitAddon(148,1), AddOutfitAddon(144,1) +Topic=3,"yes" -> "You don't have required ingredients." +Topic=3 -> "Maybe another time." + +"addon",QuestValue(18504)=2 -> "I see that you like your new bear paws!" +"paws",QuestValue(18504)=2 -> * + } diff --git a/src/behaviourdatabase.cpp b/src/behaviourdatabase.cpp index 49a8a42..2dcb678 100644 --- a/src/behaviourdatabase.cpp +++ b/src/behaviourdatabase.cpp @@ -303,6 +303,9 @@ bool BehaviourDatabase::loadActions(ScriptReader& script, NpcBehaviour* behaviou } else if (identifier == "delete") { action->type = BEHAVIOUR_TYPE_DELETE; searchType = BEHAVIOUR_PARAMETER_ONE; + } else if (identifier == "deleteamount") { + action->type = BEHAVIOUR_TYPE_DELETEAMOUNT; + searchType = BEHAVIOUR_PARAMETER_TWO; } else if (identifier == "teachspell") { action->type = BEHAVIOUR_TYPE_TEACHSPELL; searchType = BEHAVIOUR_PARAMETER_ONE; @@ -327,6 +330,12 @@ bool BehaviourDatabase::loadActions(ScriptReader& script, NpcBehaviour* behaviou } else if (identifier == "setquestvalue") { action->type = BEHAVIOUR_TYPE_QUESTVALUE; searchType = BEHAVIOUR_PARAMETER_TWO; + } else if (identifier == "setexpiringquestvalue") { + action->type = BEHAVIOUR_TYPE_EXPIRINGQUESTVALUE; + searchType = BEHAVIOUR_PARAMETER_TWO; + } else if (identifier == "addoutfitaddon") { + action->type = BEHAVIOUR_TYPE_ADDOUTFITADDON; + searchType = BEHAVIOUR_PARAMETER_TWO; } else if (identifier == "poison") { action->type = BEHAVIOUR_TYPE_POISON; searchType = BEHAVIOUR_PARAMETER_TWO; @@ -523,6 +532,10 @@ NpcBehaviourNode* BehaviourDatabase::readValue(ScriptReader& script) node = new NpcBehaviourNode(); node->type = BEHAVIOUR_TYPE_QUESTVALUE; searchType = BEHAVIOUR_PARAMETER_ONE; + } else if (identifier == "expiringquestvalue") { + node = new NpcBehaviourNode(); + node->type = BEHAVIOUR_TYPE_EXPIRINGQUESTVALUE; + searchType = BEHAVIOUR_PARAMETER_ONE; } else if (identifier == "count") { node = new NpcBehaviourNode(); node->type = BEHAVIOUR_TYPE_COUNT; @@ -854,6 +867,19 @@ void BehaviourDatabase::checkAction(const NpcBehaviourAction* action, Player* pl } break; } + case BEHAVIOUR_TYPE_DELETEAMOUNT: { + type = evaluate(action->expression, player, message); + int32_t amount = evaluate(action->expression2, player, message); + const ItemType& itemType = Item::items[type]; + if (itemType.stackable || !itemType.hasSubType()) { + data = -1; + } + + if (!player->removeItemOfType(type, amount, data, true)) { + player->removeItemOfType(type, amount, data, false); + } + break; + } case BEHAVIOUR_TYPE_EFFECTME: g_game.addMagicEffect(npc->getPosition(), evaluate(action->expression, player, message)); break; @@ -904,6 +930,18 @@ void BehaviourDatabase::checkAction(const NpcBehaviourAction* action, Player* pl player->addStorageValue(questNumber, questValue); break; } + case BEHAVIOUR_TYPE_EXPIRINGQUESTVALUE: { + int32_t questNumber = evaluate(action->expression, player, message); + int32_t ticks = evaluate(action->expression2, player, message); + player->addStorageValue(questNumber, OTSYS_TIME() + ticks); + break; + } + case BEHAVIOUR_TYPE_ADDOUTFITADDON: { + int32_t lookType = evaluate(action->expression, player, message); + int32_t addon = evaluate(action->expression2, player, message); + player->addOutfit(lookType, addon); + break; + } case BEHAVIOUR_TYPE_TELEPORT: { Position pos; pos.x = evaluate(action->expression, player, message); @@ -1072,6 +1110,12 @@ int32_t BehaviourDatabase::evaluate(NpcBehaviourNode* node, Player* player, cons player->getStorageValue(questNumber, questValue); return questValue; } + case BEHAVIOUR_TYPE_EXPIRINGQUESTVALUE: { + int32_t questNumber = evaluate(node->left, player, message); + int32_t questValue; + player->getStorageValue(questNumber, questValue); + return questValue - OTSYS_TIME(); + } case BEHAVIOUR_TYPE_MESSAGE_COUNT: { int32_t value = searchDigit(message); if (value < node->number) { diff --git a/src/behaviourdatabase.h b/src/behaviourdatabase.h index 530d4d5..b429325 100644 --- a/src/behaviourdatabase.h +++ b/src/behaviourdatabase.h @@ -86,6 +86,9 @@ enum NpcBehaviourType_t BEHAVIOUR_TYPE_CREATECONTAINER, // create a container of an item in particular BEHAVIOUR_TYPE_TOWN, // change player town BEHAVIOUR_TYPE_DRUNK, // get/set drunk (set not done) + BEHAVIOUR_TYPE_ADDOUTFITADDON, // Add Outfit Addon + BEHAVIOUR_TYPE_DELETEAMOUNT, // deletes an item according specified amount + BEHAVIOUR_TYPE_EXPIRINGQUESTVALUE, // get/set expiring quest value }; enum NpcBehaviourOperator_t diff --git a/src/luascript.cpp b/src/luascript.cpp index 93466f1..cec7652 100644 --- a/src/luascript.cpp +++ b/src/luascript.cpp @@ -2052,6 +2052,11 @@ void LuaScriptInterface::registerFunctions() registerMethod("Player", "getParty", LuaScriptInterface::luaPlayerGetParty); + registerMethod("Player", "addOutfit", LuaScriptInterface::luaPlayerAddOutfit); + registerMethod("Player", "addOutfitAddon", LuaScriptInterface::luaPlayerAddOutfitAddon); + registerMethod("Player", "removeOutfit", LuaScriptInterface::luaPlayerRemoveOutfit); + registerMethod("Player", "removeOutfitAddon", LuaScriptInterface::luaPlayerRemoveOutfitAddon); + registerMethod("Player", "hasOutfit", LuaScriptInterface::luaPlayerHasOutfit); registerMethod("Player", "sendOutfitWindow", LuaScriptInterface::luaPlayerSendOutfitWindow); registerMethod("Player", "getPremiumDays", LuaScriptInterface::luaPlayerGetPremiumDays); @@ -8259,6 +8264,80 @@ int LuaScriptInterface::luaPlayerGetParty(lua_State* L) return 1; } +int LuaScriptInterface::luaPlayerAddOutfit(lua_State* L) +{ + // player:addOutfit(lookType) + Player* player = getUserdata(L, 1); + if (player) { + player->addOutfit(getNumber(L, 2), 0); + pushBoolean(L, true); + } + else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaPlayerAddOutfitAddon(lua_State* L) +{ + // player:addOutfitAddon(lookType, addon) + Player* player = getUserdata(L, 1); + if (player) { + uint16_t lookType = getNumber(L, 2); + uint8_t addon = getNumber(L, 3); + player->addOutfit(lookType, addon); + pushBoolean(L, true); + } + else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaPlayerRemoveOutfit(lua_State* L) +{ + // player:removeOutfit(lookType) + Player* player = getUserdata(L, 1); + if (player) { + uint16_t lookType = getNumber(L, 2); + pushBoolean(L, player->removeOutfit(lookType)); + } + else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaPlayerRemoveOutfitAddon(lua_State* L) +{ + // player:removeOutfitAddon(lookType, addon) + Player* player = getUserdata(L, 1); + if (player) { + uint16_t lookType = getNumber(L, 2); + uint8_t addon = getNumber(L, 3); + pushBoolean(L, player->removeOutfitAddon(lookType, addon)); + } + else { + lua_pushnil(L); + } + return 1; +} + +int LuaScriptInterface::luaPlayerHasOutfit(lua_State* L) +{ + // player:hasOutfit(lookType[, addon = 0]) + Player* player = getUserdata(L, 1); + if (player) { + uint16_t lookType = getNumber(L, 2); + uint8_t addon = getNumber(L, 3, 0); + pushBoolean(L, player->canWear(lookType, addon)); + } + else { + lua_pushnil(L); + } + return 1; +} + int LuaScriptInterface::luaPlayerSendOutfitWindow(lua_State* L) { // player:sendOutfitWindow() diff --git a/src/luascript.h b/src/luascript.h index 90c2dd0..df7e7c4 100644 --- a/src/luascript.h +++ b/src/luascript.h @@ -882,6 +882,11 @@ class LuaScriptInterface static int luaPlayerGetParty(lua_State* L); + static int luaPlayerAddOutfit(lua_State* L); + static int luaPlayerAddOutfitAddon(lua_State* L); + static int luaPlayerRemoveOutfit(lua_State* L); + static int luaPlayerRemoveOutfitAddon(lua_State* L); + static int luaPlayerHasOutfit(lua_State* L); static int luaPlayerSendOutfitWindow(lua_State* L); static int luaPlayerGetPremiumDays(lua_State* L);