feat: Blessings (#844)

This commit is contained in:
kokekanon 2024-08-12 23:16:48 -04:00 committed by GitHub
parent c69f5bd7b9
commit d17258f576
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 460 additions and 25 deletions

View file

@ -0,0 +1,95 @@
<style>
.blessing-window {
width: 615;
height: 460;
padding-top: 36;
padding-left: 16;
padding-right: 16;
padding-bottom: 16;
font: verdana-11px-antialised;
opacity: 1;
display: block;
}
.promotion-status {
width: 583;
height: 85;
margin-top: 10;
display: block;
}
.death-penalty {
width: 583;
height: 113;
margin-top: 10;
display: block;
}
.premium-image {
margin-top: -10;
float: right;
}
.test {
display: block;
margin-top: 22;
width: 580;
}
.contenedor {
width: 580;
display: block;
font: verdana-11px-antialised;
}
.record-blessing {
width: 590;
height: 120;
display: block;
}
.mini-panel {
width: 580;
height: 350;
background-color: #404040;
margin-bottom: 10;
display: block;
}
</style>
<window id="main" anchor="parent" class="blessing-window" text="Blessings">
<minipanel class="mini-panel" text="History" id="blessingHistory" >
<UIScrollArea id ="here" layout="type: verticalBox" style="border-width: 1;border-color: #00000077;background-color:#ffffff11;height: 320;width: 570;margin-top:-12;background-color: #404040;vertical-scrollbar: ListBadgeScrollbar" >
<!--
<UIScrollArea id ="here" layout="type: verticalBox" style="height: 222;width: 570;margin-top:-12; vertical-scrollbar: ListBadgeScrollbar" >
<VerticalScrollBar id ="scroll" >
</VerticalScrollBar> -->
</UIScrollArea>
</minipanel>
<minipanel id="minipanel1" anchor="parent" class="record-blessing" text="Record of Blessings" layout="type: horizontalBox; fit-children: true;cell-size: 88 20;cell-spacing: 1">
</minipanel>
<minipanel class="promotion-status" text="Promotion and Premium Status" id="promotionStatus2">
<label id="rank" style="margin-top:12">If your account had Premium status, your XP loss would be 0% lower.</label>
<BlessingButton class="premium-image" id="premium_only"></BlessingButton>
</minipanel>
<minipanel class="death-penalty" text="Effect on Death Penalty" id="promotionStatus">
<label class="contenedor" id="fightRules">- Depending on the fair fight rules, you will lose between 2% and 1% less
XP and skill </br> \n points upon your next PvP death.</label>
<label class="contenedor" id="expLoss">- You will lose 3% less XP and skill points upon your next PvE death.</label>
<label class="contenedor" id="containerLoss">- There is a 2% chance that you will lose your equipped container on
your next\n death.</label>
<label class="contenedor" id="equipmentLoss">- There is a 1% chance that you will lose items upon your next
death.</label>
</minipanel>
<HorizontalSeparator class="test"></HorizontalSeparator>
<button style="margin-top:18;margin-left:370" onclick="self:showHistory()" id="historyButton">history</button> <!-- temporal fix -->
<button style="margin-top:18" onclick="self:close()">close</button>
</window>

View file

@ -0,0 +1,138 @@
BlessingController = Controller:new()
function BlessingController:onInit()
end
function BlessingController:onTerminate()
-- BlessingController:findWidget("#main"):destroy()
end
function BlessingController:onGameStart()
g_ui.importStyle("style.otui")
BlessingController:loadHtml('blessing.html', g_ui.getRootWidget())
BlessingController:registerEvents(g_game, {
onUpdateBlessDialog = onUpdateBlessDialog
})
BlessingController.ui:hide()
BlessingController.ui.minipanel1:setText("Record of Blessings") -- Temp fix html/css system
end
function BlessingController:onGameEnd()
if BlessingController.ui:isVisible() then
BlessingController.ui:hide()
end
end
function BlessingController:close()
hide()
end
function BlessingController:showHistory()
if BlessingController.ui.blessingHistory:isVisible() then
setBlessing()
else
setHistory()
end
end
function setHistory()
local ui = BlessingController.ui
ui.minipanel1:hide()
ui.promotionStatus2:hide()
ui.promotionStatus:hide()
ui.blessingHistory:show()
ui.historyButton:setText("Back")
end
function setBlessing()
local ui = BlessingController.ui
ui.minipanel1:show()
ui.promotionStatus2:show()
ui.promotionStatus:show()
ui.blessingHistory:hide()
ui.historyButton:setText("History")
end
function toggle()
if not BlessingController.ui then
return
end
if BlessingController.ui:isVisible() then
return hide()
end
show()
end
function hide()
if not BlessingController.ui then
return
end
BlessingController.ui:hide()
end
function show()
if not BlessingController.ui then
return
end
g_game.requestBless()
BlessingController.ui:show()
BlessingController.ui:raise()
BlessingController.ui:focus()
setBlessing()
end
function onUpdateBlessDialog(data)
BlessingController.ui.minipanel1:destroyChildren()
for i, entry in ipairs(data.blesses) do
local label = g_ui.createWidget("blessingTEST", BlessingController.ui.minipanel1)
local totalCount = entry.playerBlessCount + entry.store
label.text:setText(entry.playerBlessCount .. " (" .. entry.store .. ")")
if totalCount >= 1 then
label.enabled:setImageSource("images/" .. i .. "_on")
end
end
if (data.promotion ~= 0) then
BlessingController.ui.promotionStatus2.premium_only:setOn(true)
BlessingController.ui.promotionStatus2.rank:setColoredText(
"Your character is promoted and your account has Premium\nstatus. As a result, your XP loss is reduced by {30%, #f75f5f}.")
else
BlessingController.ui.promotionStatus2.rank:setColoredText(
"Your character is promoted and your account has Premium\nstatus. As a result, your XP loss is reduced by {0%, #f75f5f}.")
BlessingController.ui.promotionStatus2.premium_only:setOn(false)
end
BlessingController.ui.promotionStatus.fightRules:setColoredText(
"- Depending on the fair fight rules, you will lose between {" .. data.pvpMinXpLoss .. ", #f75f5f} and {" ..
data.pvpMaxXpLoss .. "%, #f75f5f} less XP and skill points \nupon your next PvP death.")
BlessingController.ui.promotionStatus.expLoss:setColoredText(
"- You will lose {" .. data.pveExpLoss .. "%, #f75f5f}% less XP and skill points upon your next PvE death.")
BlessingController.ui.promotionStatus.containerLoss:setColoredText(
"- There is a {" .. data.equipPvpLoss ..
"%, #f75f5f} chance that you will lose your equipped container on your next death.")
BlessingController.ui.promotionStatus.equipmentLoss:setColoredText(
"- There is a {" .. data.equipPveLoss .. "%, #f75f5f} chance that you will lose items upon your next death.")
BlessingController.ui.blessingHistory:getChildByIndex(1):destroyChildren()
local row2 = g_ui.createWidget("historyData", BlessingController.ui.blessingHistory:getChildByIndex(1))
row2:setBackgroundColor("#363636")
row2.rank:setText("date")
row2.name:setText("Event")
row2.rank:setColor("#c0c0c0")
row2.name:setColor("#c0c0c0")
row2:setBorderColor("#00000077")
row2:setBorderWidth(1)
for index, entry in ipairs(data.logs) do
local row = g_ui.createWidget("historyData", BlessingController.ui.blessingHistory:getChildByIndex(1))
local date = os.date("%Y-%m-%d, %H:%M:%S", entry.timestamp)
row:setBackgroundColor(index % 2 == 0 and "#ffffff12" or "#00000012")
row.rank:setText(date)
row.name:setText(entry.historyMessage)
end
end

View file

@ -0,0 +1,9 @@
Module
name: game_blessing
description: game_blessing
author: game_blessing
website: game_blessing
scripts: [ blessing.lua ]
sandboxed: true
@onLoad: BlessingController:init()
@onUnload: BlessingController:terminate()

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View file

@ -0,0 +1,74 @@
historyData < UIWidget
height: 16
Label
anchors.top: parent.top
anchors.left: parent.left
anchors.bottom : parent.bottom
id: rank
width: 150
!text: tr('1')
text-align: center
color: #dfdfdfcf
phantom: false
margin-left: 4
VerticalSeparator
id: separator
anchors.top: parent.top
anchors.left: parent.left
anchors.bottom: parent.bottom
margin-top: -1
margin-bottom: -1
margin-left: 155
Label
anchors.top: parent.top
anchors.left: prev.right
anchors.bottom : parent.bottom
id: name
width: 216
!text: tr('-')
text-align: left
color: #ff0000cf
phantom: true
margin-left: 5
blessingTEST < UIWidget
background-color: alpha
height: 62
width: 70
focusable: true
text-align: left
UIWidget
id: enabled
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
margin-top: -10
margin-left: 3
Label
id: text
!text: tr('loooooong text')
text-align: center
margin-top: 5
width: 65
anchors.left: prev.left
anchors.top: prev.bottom
image-source: /game_blessing/images/blessingContainer
focusable: false
BlessingButton < UIButton
size: 128 37
image-source: /game_blessing/images/getpremium
image-clip: 0 0 128 37
image-border: 3
@onClick: modules.game_mainpanel.toggleStore()
$pressed:
image-clip: 0 37 128 37
$!on:
image-clip: 0 74 128 37
$disabled:
color: #dfdfdf88
opacity: 0.8

View file

@ -42,6 +42,7 @@ Module
- game_shop
- game_screenshot
- game_highscore
- game_blessing
- game_store
- game_quickloot

View file

@ -68,7 +68,7 @@ PhantomMiniWindow
anchors.left: changeSize.right
margin-left: 3
size: 12 12
@onClick: modules.game_blessing.toggle()
$pressed !disabled:
image-clip: 12 0 12 12
@ -556,7 +556,7 @@ PhantomMiniWindow
anchors.left: changeSize.left
margin-top: 3
size: 12 12
@onClick: modules.game_blessing.toggle()
$pressed !disabled:
image-clip: 12 0 12 12

View file

@ -1726,6 +1726,14 @@ void Game::imbuementDurations(bool isOpen)
m_protocolGame->sendImbuementDurations(isOpen);
}
void Game::requestBless()
{
if (!canPerformGameAction())
return;
m_protocolGame->sendRequestBless();
}
void Game::requestQuickLootBlackWhiteList(uint8_t filter, uint16_t size, const std::vector<uint16_t>& listedItems)
{
m_denyBotCall = false;

View file

@ -53,6 +53,36 @@ struct UnjustifiedPoints
uint8_t skullTime;
};
struct BlessData
{
uint16_t blessBitwise;
uint8_t playerBlessCount;
uint8_t store;
};
struct LogData
{
uint32_t timestamp;
uint8_t colorMessage;
std::string_view historyMessage;
};
struct BlessDialogData
{
uint8_t totalBless;
std::vector<BlessData> blesses;
uint8_t premium;
uint8_t promotion;
uint8_t pvpMinXpLoss;
uint8_t pvpMaxXpLoss;
uint8_t pveExpLoss;
uint8_t equipPvpLoss;
uint8_t equipPveLoss;
uint8_t skull;
uint8_t aol;
std::vector<LogData> logs;
};
using Vip = std::tuple<std::string, uint32_t, std::string, int, bool>;
struct StoreCategory
@ -483,6 +513,7 @@ public:
const std::vector<std::tuple<uint32_t, std::string, std::string, uint8_t, std::string, uint16_t, uint8_t, uint64_t>>& highscores, uint32_t entriesTs);
void imbuementDurations(bool isOpen = false);
void requestBless();
void requestQuickLootBlackWhiteList(uint8_t filter, uint16_t size, const std::vector<uint16_t>& listedItems);
void openContainerQuickLoot(uint8_t action, uint8_t category, const Position& pos, uint16_t itemId, uint8_t stackpos, bool useMainAsFallback);

View file

@ -362,6 +362,7 @@ void Client::registerLuaFunctions()
g_lua.bindSingletonFunction("g_game", "stashWithdraw", &Game::stashWithdraw, &g_game);
g_lua.bindSingletonFunction("g_game", "requestHighscore", &Game::requestHighscore, &g_game);
g_lua.bindSingletonFunction("g_game", "imbuementDurations", &Game::imbuementDurations, &g_game);
g_lua.bindSingletonFunction("g_game", "requestBless", &Game::requestBless, &g_game);
g_lua.bindSingletonFunction("g_game", "requestQuickLootBlackWhiteList", &Game::requestQuickLootBlackWhiteList, &g_game);
g_lua.bindSingletonFunction("g_game", "openContainerQuickLoot", &Game::openContainerQuickLoot, &g_game);

View file

@ -289,6 +289,69 @@ bool luavalue_cast(int index, UnjustifiedPoints& unjustifiedPoints)
return true;
}
int push_luavalue(const BlessData& bless) {
g_lua.createTable(0, 3);
g_lua.pushInteger(bless.blessBitwise);
g_lua.setField("blessBitwise");
g_lua.pushInteger(bless.playerBlessCount);
g_lua.setField("playerBlessCount");
g_lua.pushInteger(bless.store);
g_lua.setField("store");
return 1;
}
int push_luavalue(const LogData& log) {
g_lua.createTable(0, 3);
g_lua.pushInteger(log.timestamp);
g_lua.setField("timestamp");
g_lua.pushInteger(log.colorMessage);
g_lua.setField("colorMessage");
g_lua.pushString(log.historyMessage);
g_lua.setField("historyMessage");
return 1;
}
int push_luavalue(const BlessDialogData& data) {
g_lua.createTable(0, 11);
g_lua.pushInteger(data.totalBless);
g_lua.setField("totalBless");
g_lua.createTable(data.blesses.size(), 0);
for (size_t i = 0; i < data.blesses.size(); ++i) {
push_luavalue(data.blesses[i]);
g_lua.rawSeti(i + 1);
}
g_lua.setField("blesses");
g_lua.pushInteger(data.premium);
g_lua.setField("premium");
g_lua.pushInteger(data.promotion);
g_lua.setField("promotion");
g_lua.pushInteger(data.pvpMinXpLoss);
g_lua.setField("pvpMinXpLoss");
g_lua.pushInteger(data.pvpMaxXpLoss);
g_lua.setField("pvpMaxXpLoss");
g_lua.pushInteger(data.pveExpLoss);
g_lua.setField("pveExpLoss");
g_lua.pushInteger(data.equipPvpLoss);
g_lua.setField("equipPvpLoss");
g_lua.pushInteger(data.equipPveLoss);
g_lua.setField("equipPveLoss");
g_lua.pushInteger(data.skull);
g_lua.setField("skull");
g_lua.pushInteger(data.aol);
g_lua.setField("aol");
g_lua.createTable(data.logs.size(), 0);
for (size_t i = 0; i < data.logs.size(); ++i) {
push_luavalue(data.logs[i]);
g_lua.rawSeti(i + 1);
}
g_lua.setField("logs");
return 1;
}
int push_luavalue(const StoreCategory& category) {
g_lua.createTable(0, 5);
g_lua.pushString(category.name);

View file

@ -49,6 +49,11 @@ bool luavalue_cast(int index, UnjustifiedPoints& unjustifiedPoints);
int push_luavalue(const Imbuement& i);
int push_luavalue(const ImbuementTrackerItem& i);
// Bless
int push_luavalue(const BlessData& bless);
int push_luavalue(const LogData& log);
int push_luavalue(const BlessDialogData& data);
// Store
int push_luavalue(const StoreCategory& category);
int push_luavalue(const SubOffer& subOffer);
int push_luavalue(const StoreOffer& offer);

View file

@ -298,6 +298,7 @@ namespace Proto
ClientRefreshContainer = 202,
ClientBrowseField = 203,
ClientSeekInContainer = 204,
ClientRequestBless = 207,
ClientRequestOutfit = 210,
ClientChangeOutfit = 211,
ClientMount = 212, // 870

View file

@ -97,6 +97,7 @@ public:
void sendExcludeFromOwnChannel(const std::string_view name);
void sendCancelAttackAndFollow();
void sendRefreshContainer(int containerId);
void sendRequestBless();
void sendRequestOutfit();
void sendChangeOutfit(const Outfit& outfit);
void sendTyping(bool typing);

View file

@ -3713,36 +3713,37 @@ void ProtocolGame::parseGameNews(const InputMessagePtr& msg)
void ProtocolGame::parseBlessDialog(const InputMessagePtr& msg)
{
// parse bless amount
const uint8_t totalBless = msg->getU8(); // total bless
BlessDialogData data;
// parse each bless
for (auto i = 0; i < totalBless; ++i) {
msg->getU16(); // bless bit wise
msg->getU8(); // player bless count
msg->getU8(); // store?
data.totalBless = msg->getU8();
for (auto i = 0; i < data.totalBless; ++i) {
BlessData bless;
bless.blessBitwise = msg->getU16();
bless.playerBlessCount = msg->getU8();
bless.store = msg->getU8();
data.blesses.emplace_back(bless);
}
// parse general info
msg->getU8(); // premium
msg->getU8(); // promotion
msg->getU8(); // pvp min xp loss
msg->getU8(); // pvp max xp loss
msg->getU8(); // pve exp loss
msg->getU8(); // equip pvp loss
msg->getU8(); // equip pve loss
msg->getU8(); // skull
msg->getU8(); // aol
data.premium = msg->getU8();
data.promotion = msg->getU8();
data.pvpMinXpLoss = msg->getU8();
data.pvpMaxXpLoss = msg->getU8();
data.pveExpLoss = msg->getU8();
data.equipPvpLoss = msg->getU8();
data.equipPveLoss = msg->getU8();
data.skull = msg->getU8();
data.aol = msg->getU8();
// parse log
const uint8_t logCount = msg->getU8(); // log count
const uint8_t logCount = msg->getU8();
for (auto i = 0; i < logCount; ++i) {
msg->getU32(); // timestamp
msg->getU8(); // color message (0 = white loss, 1 = red)
msg->getString(); // history message
LogData log;
log.timestamp = msg->getU32();
log.colorMessage = msg->getU8();
log.historyMessage = msg->getString();
data.logs.emplace_back(log);
}
// TODO: implement bless dialog usage
g_lua.callGlobalField("g_game", "onUpdateBlessDialog", data);
}
void ProtocolGame::parseRestingAreaState(const InputMessagePtr& msg)

View file

@ -725,6 +725,13 @@ void ProtocolGame::sendRefreshContainer(int containerId)
send(msg);
}
void ProtocolGame::sendRequestBless()
{
const auto& msg = std::make_shared<OutputMessage>();
msg->addU8(Proto::ClientRequestBless);
send(msg);
}
void ProtocolGame::sendRequestOutfit()
{
const auto& msg = std::make_shared<OutputMessage>();