Skip to content
This repository has been archived by the owner on Dec 4, 2020. It is now read-only.

Commit

Permalink
Mystery box additions (#434)
Browse files Browse the repository at this point in the history
* Daily tally item load & selection
* Arbitrix rough basic functionality
  • Loading branch information
cocosolos authored Mar 26, 2020
1 parent a0ed0f5 commit 9daa61c
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 40 deletions.
98 changes: 80 additions & 18 deletions scripts/zones/Windurst_Walls/npcs/Arbitrix.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,47 +7,109 @@
local ID = require("scripts/zones/Windurst_Walls/IDs")
require("scripts/globals/settings")
-----------------------------------
local adoulinOptionOff = 0x80
local pictlogicaOptionOff = 0x100
local wantedOptionOff = 0x1000
local hideOptionFlags = adoulinOptionOff + pictlogicaOptionOff + wantedOptionOff
local costs =
{
[1] = 10,
[2] = 10,
[3] = 10,
[4] = 10,
[5] = 10,
[6] = 50
}

function onTrigger(player, npc)
local playerAgeDays = (os.time() - player:getTimeCreated()) / 86400

local dailyTallyPoints = player:getCurrency("daily_tally")
local firstVisit = dailyTallyPoints == -1

local gobbieBoxUsed = player:getCharVar("gobbieBoxUsed")
local specialDialUsed = 1
local adoulinDialUsed = 1
local pictlogicaDialUsed = 1
local wantedDialUsed = 1

local adoulinOptionOff = 0x80
local pictlogicaOptionOff = 0x100
local wantedOptionOff = 0x1000
local hideOptionFlags = adoulinOptionOff + pictlogicaOptionOff + wantedOptionOff
local specialDialUsed = player:getMaskBit(gobbieBoxUsed, 0) and 1 or 0
local adoulinDialUsed = player:getMaskBit(gobbieBoxUsed, 1) and 1 or 0
local pictlogicaDialUsed = player:getMaskBit(gobbieBoxUsed, 2) and 1 or 0
local wantedDialUsed = player:getMaskBit(gobbieBoxUsed, 3) and 1 or 0
local holdingItem = player:getCharVar("gobbieBoxHoldingItem")

if playerAgeDays >= GOBBIE_BOX_MIN_AGE and firstVisit then
player:startEvent(519)
elseif playerAgeDays >= GOBBIE_BOX_MIN_AGE then
player:startEvent(520, specialDialUsed, adoulinDialUsed, pictlogicaDialUsed, wantedDialUsed, 0, 0, hideOptionFlags, dailyTallyPoints)
if holdingItem ~= 0 then
player:startEvent(521)
else
player:startEvent(520, specialDialUsed, adoulinDialUsed, pictlogicaDialUsed, wantedDialUsed, 0, 0, hideOptionFlags, dailyTallyPoints)
end
else
player:messageSpecial(ID.text.YOU_MUST_WAIT_ANOTHER_N_DAYS, GOBBIE_BOX_MIN_AGE - playerAgeDays)
end
end

function onEventUpdate(player, csid, option)
local dailyTallyPoints = player:getCurrency("daily_tally")
local holdingItem = player:getCharVar("gobbieBoxHoldingItem")
local gobbieBoxUsed = player:getCharVar("gobbieBoxUsed")
local specialDialUsed = player:getMaskBit(gobbieBoxUsed, 0) and 1 or 0
local adoulinDialUsed = player:getMaskBit(gobbieBoxUsed, 1) and 1 or 0
local pictlogicaDialUsed = player:getMaskBit(gobbieBoxUsed, 2) and 1 or 0
local wantedDialUsed = player:getMaskBit(gobbieBoxUsed, 3) and 1 or 0
local itemid = 0

if csid == 520 and option == 4 then -- Peek items
player:updateEvent(200, 200, 200)
elseif csid == 520 and option == 9 then
player:updateEvent(1, 1, (dailyTallyPoints >= 10) or 1)
elseif csid == 520 and option == 10 then
-- Deliver Dial 1
if csid == 520 then
if option == 4 then
player:updateEvent(SelectDailyItem(player, 6), SelectDailyItem(player, 6), SelectDailyItem(player, 6), 0, 0, 0, 0, dailyTallyPoints) -- peek
else
local dial = math.floor(option / 8)
local option_type = option % 8
local dial_used = false
local dial_cost = costs[dial]
local dial_mask = false
if dial >= 6 then
dial_mask = dial - 6
dial_used = player:getMaskBit(gobbieBoxUsed, dial_mask)
end
switch (option_type): caseof
{
[1] = function()
if dial_used then
player:updateEvent(1, dial, 2) -- already used this dial
elseif dailyTallyPoints >= dial_cost then
itemid = SelectDailyItem(player, dial)
player:setCharVar("gobbieBoxHoldingItem", itemid)
player:setCurrency("daily_tally", dailyTallyPoints - dial_cost)
if dial_mask then
player:setMaskBit(gobbieBoxUsed, "gobbieBoxUsed", dial_mask, true)
end
player:updateEvent(itemid, dial, 0)
else
player:updateEvent(1, dial, 1) -- not enough points
end
end,
[2] = function()
if player:getFreeSlotsCount() == 0 then
player:updateEvent(holdingItem, 0, 0, 1) -- inventory full, exit event
player:messageSpecial(ID.text.ITEM_CANNOT_BE_OBTAINED + 2) -- generic "Cannot obtain the item."
end
end,
[5] = function()
if holdingItem > 0 and npcUtil.giveItem(player, holdingItem) then
player:setCharVar("gobbieBoxHoldingItem", 0)
end
player:updateEvent(specialDialUsed, adoulinDialUsed, pictlogicaDialUsed, wantedDialUsed, 0, 0, hideOptionFlags, dailyTallyPoints)
end,
}
end
end
end

function onEventFinish(player, csid, option)
if csid == 519 then
player:setCurrency("daily_tally", 50)
elseif csid == 521 then
if player:getFreeSlotsCount() == 0 then
player:messageSpecial(ID.text.ITEM_CANNOT_BE_OBTAINED + 2) -- generic "Cannot obtain the item."
elseif npcUtil.giveItem(player, player:getCharVar("gobbieBoxHoldingItem")) then
player:setCharVar("gobbieBoxHoldingItem", 0)
end
end
end
188 changes: 167 additions & 21 deletions src/map/daily_system.cpp
Original file line number Diff line number Diff line change
@@ -1,34 +1,180 @@
#include "daily_system.h"

#include "map.h"
#include "items/item.h"
#include "utils/charutils.h"
#include "utils/itemutils.h"

namespace daily
{
void UpdateDailyTallyPoints()
{
uint16 dailyTallyLimit = map_config.daily_tally_limit;
uint16 dailyTallyAmount = map_config.daily_tally_amount;

const char* fmtQuery = "UPDATE char_points \
SET char_points.daily_tally = LEAST(%u, char_points.daily_tally + %u) \
WHERE char_points.daily_tally > -1;";
std::vector<uint16> materialsDialItems;
std::vector<uint16> foodDialItems;
std::vector<uint16> medicineDialItems;
std::vector<uint16> sundries1DialItems;
std::vector<uint16> sundries2DialItems;
std::vector<uint16> specialDialItems;

int32 ret = Sql_Query(SqlHandle, fmtQuery, dailyTallyLimit, dailyTallyAmount);

if (ret == SQL_ERROR)
uint16 SelectItem(CCharEntity* player, uint8 dial)
{
ShowError("Failed to update daily tally points\n");
int selection;
std::vector<uint16> dialItems;
switch (dial)
{
case 1:
{
dialItems = materialsDialItems;
break;
}
case 2:
{
dialItems = foodDialItems;
break;
}
case 3:
{
dialItems = medicineDialItems;
break;
}
case 4:
{
dialItems = sundries1DialItems;
break;
}
case 5:
{
dialItems = sundries2DialItems;
break;
}
case 6:
{
dialItems = specialDialItems;
break;
}
}
do
{
selection = std::rand() % dialItems.size();
} while ((itemutils::GetItem(dialItems[selection])->getFlag() & ITEM_FLAG_RARE) > 0 && charutils::HasItem(player, dialItems[selection]));
return dialItems[selection];
}
else

void LoadDailyItems()
{
ShowDebug("Distributed daily tally points\n");
}
int32 ret = Sql_Query(SqlHandle, "SELECT itemid, aH, flags FROM item_basic WHERE flags & 4 > 0");
uint16 itemid, aH, flags;

fmtQuery = "DELETE FROM char_vars WHERE varname = 'gobbieBoxUsed';";
if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0)
{
while (Sql_NextRow(SqlHandle) == SQL_SUCCESS)
{
itemid = Sql_GetUIntData(SqlHandle,0);
aH = Sql_GetUIntData(SqlHandle,1);
flags = Sql_GetUIntData(SqlHandle,2);
specialDialItems.push_back(itemid);
switch (aH)
{
/* Dial 1 (Materials) */
case 38: // Smithing
case 39: // Goldsmithing
case 40: // Clothcrafting
case 41: // Leathercrafting
case 42: // Bonecrafting
case 43: // Woodworking
case 44: // Alchemy
case 50: // Beast-Made
{
materialsDialItems.push_back(itemid);
break;
}
/* Dial 2 (Food) */
case 52: // Meat & Eggs
case 53: // Seafood
case 54: // Vegetables
case 55: // Soups
case 56: // Breads & Rice
case 57: // Sweets
case 58: // Drinks
{
foodDialItems.push_back(itemid);
break;
}
/* Dial 3 (Medicine) */
case 33: // Medicine
{
medicineDialItems.push_back(itemid);
break;
}
/* Dial 4 (Sundries 1) */
case 15: // Ammunition
case 36: // Cards
case 49: // Ninja Tools
{
if ((flags & ITEM_FLAG_CANUSE) > 0) // only usable (pouch, case, quiver, etc)
{
sundries1DialItems.push_back(itemid);
}
break;
}
/* Dial 5 (Sundries 2) */
case 47: // Fishing Gear
case 51: // Fish
{
if (itemid == 489 || itemid == 17386) // Lu Shang is probably only special dial
{
break;
}
sundries2DialItems.push_back(itemid);
break;
}
default:
{
switch (itemid)
{
case 605: // pickaxe
case 1020: // sickle
case 1021: // hatchet
case 1022: // thief's tools
case 1023: // living key
case 15453: // lugworm belt
case 15454: // little worm belt
{
sundries2DialItems.push_back(itemid);
break;
}
}
}
}
}
}
else
{
ShowError("Failed to load daily tally items\n");
}
}

if (Sql_Query(SqlHandle, fmtQuery, dailyTallyAmount) == SQL_ERROR)
void UpdateDailyTallyPoints()
{
ShowError("Failed to delete daily tally char_vars entries");
uint16 dailyTallyLimit = map_config.daily_tally_limit;
uint16 dailyTallyAmount = map_config.daily_tally_amount;

const char* fmtQuery = "UPDATE char_points \
SET char_points.daily_tally = LEAST(%u, char_points.daily_tally + %u) \
WHERE char_points.daily_tally > -1;";

int32 ret = Sql_Query(SqlHandle, fmtQuery, dailyTallyLimit, dailyTallyAmount);

if (ret == SQL_ERROR)
{
ShowError("Failed to update daily tally points\n");
}
else
{
ShowDebug("Distributed daily tally points\n");
}

fmtQuery = "DELETE FROM char_vars WHERE varname = 'gobbieBoxUsed';";

if (Sql_Query(SqlHandle, fmtQuery, dailyTallyAmount) == SQL_ERROR)
{
ShowError("Failed to delete daily tally char_vars entries");
}
}
}
}
5 changes: 4 additions & 1 deletion src/map/daily_system.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#ifndef _DAILYSYSTEM_H
#define _DAILYSYSTEM_H
#include "map.h"

namespace daily
{
void UpdateDailyTallyPoints();
uint16 SelectItem(CCharEntity* player, uint8 dial);
void LoadDailyItems();
void UpdateDailyTallyPoints();
}

#endif //_DAILYSYSTEM_H
1 change: 1 addition & 0 deletions src/map/lua/lua_baseentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "../ability.h"
#include "../alliance.h"
#include "../battlefield.h"
#include "../daily_system.h"
#include "../enmity_container.h"
#include "../guild.h"
#include "../instance.h"
Expand Down
12 changes: 12 additions & 0 deletions src/map/lua/luautils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
#include "../ai/states/magic_state.h"
#include <optional>
#include "../battlefield.h"
#include "../daily_system.h"

namespace luautils
{
Expand Down Expand Up @@ -148,6 +149,7 @@ namespace luautils

lua_register(LuaHandle, "getAbility", luautils::getAbility);
lua_register(LuaHandle, "getSpell", luautils::getSpell);
lua_register(LuaHandle, "SelectDailyItem", luautils::SelectDailyItem);

Lunar<CLuaAbility>::Register(LuaHandle);
Lunar<CLuaAction>::Register(LuaHandle);
Expand Down Expand Up @@ -4509,4 +4511,14 @@ namespace luautils
}
}

int32 SelectDailyItem(lua_State* L)
{
TPZ_DEBUG_BREAK_IF(lua_isnil(L, 1) || !lua_isuserdata(L, 1));
TPZ_DEBUG_BREAK_IF(lua_isnil(L, 2) || !lua_isnumber(L, 2));
CLuaBaseEntity* PLuaBaseEntity = Lunar<CLuaBaseEntity>::check(L, 1);
CCharEntity* player = (CCharEntity*)PLuaBaseEntity->GetBaseEntity();
lua_pushinteger(L, daily::SelectItem(player, (uint8)lua_tointeger(L, 2)));
return 1;
}

}; // namespace luautils
2 changes: 2 additions & 0 deletions src/map/lua/luautils.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ namespace luautils

void OnFurniturePlaced(CCharEntity* PChar, CItemFurnishing* itemId);
void OnFurnitureRemoved(CCharEntity* PChar, CItemFurnishing* itemId);

int32 SelectDailyItem(lua_State* L);
};

#endif //- _LUAUTILS_H -
Loading

0 comments on commit 9daa61c

Please sign in to comment.