Jink&null (#32)
* rewrite toUtf8().data() * jink, askforuse, askforresp * nullification
This commit is contained in:
parent
c4f90a50c7
commit
22235ee6ec
|
@ -256,6 +256,9 @@ Fk:loadTranslationTable{
|
|||
["$Equip"] = "装备区",
|
||||
["$Judge"] = "判定区",
|
||||
["#AskForUseActiveSkill"] = "请使用技能 %1",
|
||||
["#AskForUseCard"] = "请使用卡牌 %1",
|
||||
["#AskForResponseCard"] = "请打出卡牌 %1",
|
||||
["#AskForNullification"] = "无懈",
|
||||
|
||||
["Trust"] = "托管",
|
||||
["Sort Cards"] = "牌序",
|
||||
|
|
|
@ -295,7 +295,7 @@ end
|
|||
---@param players ServerPlayer[]
|
||||
function Room:doRaceRequest(command, players, jsonData)
|
||||
players = players or self.players
|
||||
self:notifyMoveFocus(players, command)
|
||||
-- self:notifyMoveFocus(players, command)
|
||||
for _, p in ipairs(players) do
|
||||
self:doRequest(p, command, jsonData or p.request_data, false)
|
||||
end
|
||||
|
@ -304,6 +304,7 @@ function Room:doRaceRequest(command, players, jsonData)
|
|||
local currentTime = os.time()
|
||||
local elapsed = 0
|
||||
local winner
|
||||
local canceled_players = {}
|
||||
while true do
|
||||
elapsed = os.time() - currentTime
|
||||
if remainTime - elapsed <= 0 then
|
||||
|
@ -315,11 +316,19 @@ function Room:doRaceRequest(command, players, jsonData)
|
|||
winner = p
|
||||
break
|
||||
end
|
||||
|
||||
if p.reply_cancel then
|
||||
table.insertIfNeed(canceled_players, p)
|
||||
end
|
||||
end
|
||||
if winner then
|
||||
self:doBroadcastNotify("CancelRequest", "")
|
||||
return winner
|
||||
end
|
||||
|
||||
if #players == #canceled_players then
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -566,8 +575,104 @@ function Room:askForSkillInvoke(player, skill_name, data)
|
|||
return invoked
|
||||
end
|
||||
|
||||
function Room:askForUseCard() end
|
||||
function Room:askForResponse() end
|
||||
---@param player ServerPlayer
|
||||
---@return CardUseStruct
|
||||
function Room:askForUseCard(player, card_name, prompt, cancelable, extra_data)
|
||||
local command = "AskForUseCard"
|
||||
self:notifyMoveFocus(player, card_name)
|
||||
cancelable = cancelable or false
|
||||
extra_data = extra_data or {}
|
||||
prompt = prompt or "#AskForUseCard"
|
||||
|
||||
local data = {card_name, prompt, cancelable, extra_data}
|
||||
local result = self:doRequest(player, command, json.encode(data))
|
||||
if result ~= "" then
|
||||
data = json.decode(result)
|
||||
local card = data.card
|
||||
local targets = data.targets
|
||||
if type(card) == "string" then
|
||||
-- TODO: ViewAsSkill
|
||||
return nil
|
||||
else
|
||||
local use = {} ---@type CardUseStruct
|
||||
use.from = player.id
|
||||
use.tos = {}
|
||||
for _, target in ipairs(targets) do
|
||||
table.insert(use.tos, { target })
|
||||
end
|
||||
if #use.tos == 0 then
|
||||
use.tos = nil
|
||||
end
|
||||
use.cardId = card
|
||||
return use
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Room:askForResponse(player, card_name, prompt, cancelable, extra_data)
|
||||
local command = "AskForResponseCard"
|
||||
self:notifyMoveFocus(player, card_name)
|
||||
cancelable = cancelable or false
|
||||
extra_data = extra_data or {}
|
||||
prompt = prompt or "#AskForResponseCard"
|
||||
|
||||
local data = {card_name, prompt, cancelable, extra_data}
|
||||
local result = self:doRequest(player, command, json.encode(data))
|
||||
if result ~= "" then
|
||||
data = json.decode(result)
|
||||
local card = data.card
|
||||
local targets = data.targets
|
||||
if type(card) == "string" then
|
||||
-- TODO: ViewAsSkill
|
||||
return nil
|
||||
else
|
||||
return card
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Room:askForNullification(players, card_name, prompt, cancelable, extra_data)
|
||||
if #players == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
local command = "AskForUseCard"
|
||||
card_name = card_name or "nullification"
|
||||
cancelable = cancelable or false
|
||||
extra_data = extra_data or {}
|
||||
prompt = prompt or "#AskForUseCard"
|
||||
|
||||
self:notifyMoveFocus(self.players, card_name)
|
||||
self:doBroadcastNotify("WaitForNullification", "")
|
||||
|
||||
local data = {card_name, prompt, cancelable, extra_data}
|
||||
local winner = self:doRaceRequest(command, players, json.encode(data))
|
||||
if winner then
|
||||
local result = winner.client_reply
|
||||
data = json.decode(result)
|
||||
local card = data.card
|
||||
local targets = data.targets
|
||||
if type(card) == "string" then
|
||||
-- TODO: ViewAsSkill
|
||||
return nil
|
||||
else
|
||||
local use = {} ---@type CardUseStruct
|
||||
use.from = winner.id
|
||||
use.tos = {}
|
||||
for _, target in ipairs(targets) do
|
||||
table.insert(use.tos, { target })
|
||||
end
|
||||
if #use.tos == 0 then
|
||||
use.tos = nil
|
||||
end
|
||||
use.cardId = card
|
||||
return use
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- use card logic, and wrappers
|
||||
|
@ -580,7 +685,7 @@ function Room:askForResponse() end
|
|||
local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
||||
local eventStages = { fk.TargetSpecifying, fk.TargetConfirming, fk.TargetSpecified, fk.TargetConfirmed }
|
||||
for _, stage in ipairs(eventStages) do
|
||||
if not cardUseEvent.tos then
|
||||
if (not cardUseEvent.tos) or #cardUseEvent.tos == 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
|
@ -871,8 +976,6 @@ function Room:doCardEffect(cardEffectEvent)
|
|||
end
|
||||
|
||||
if event == fk.PreCardEffect then
|
||||
-- TODO: use jink
|
||||
|
||||
if Fk:getCardById(cardEffectEvent.cardId).name == 'slash' and
|
||||
not (
|
||||
cardEffectEvent.disresponsive or
|
||||
|
@ -880,38 +983,31 @@ function Room:doCardEffect(cardEffectEvent)
|
|||
table.contains(cardEffectEvent.disresponsiveList or {}, cardEffectEvent.to) or
|
||||
table.contains(cardEffectEvent.unoffsetableList or {}, cardEffectEvent.to)
|
||||
) then
|
||||
local result = self:doRequest(self:getPlayerById(cardEffectEvent.to), "PlayCard", cardEffectEvent.to)
|
||||
if result ~= '' then
|
||||
local data = json.decode(result)
|
||||
local card = data.card
|
||||
local targets = data.targets
|
||||
if type(card) == "string" then
|
||||
local card_data = json.decode(card)
|
||||
local skill = Fk.skills[card_data.skill]
|
||||
local selected_cards = card_data.subcards
|
||||
skill:onEffect(self, {
|
||||
from = cardEffectEvent.to,
|
||||
cards = selected_cards,
|
||||
tos = targets,
|
||||
})
|
||||
else
|
||||
local use = {} ---@type CardUseStruct
|
||||
use.from = cardEffectEvent.to
|
||||
local to = self:getPlayerById(cardEffectEvent.to)
|
||||
local use = self:askForUseCard(to, "jink")
|
||||
if use then
|
||||
use.toCardId = cardEffectEvent.cardId
|
||||
use.responseToEvent = cardEffectEvent
|
||||
use.cardId = card
|
||||
self:useCard(use)
|
||||
end
|
||||
end
|
||||
elseif Fk:getCardById(cardEffectEvent.cardId).type == Card.TypeTrick then
|
||||
-- TODO: use nullification
|
||||
local players = {}
|
||||
for _, p in ipairs(self.players) do
|
||||
local cards = p.player_cards[Player.Hand]
|
||||
for _, cid in ipairs(cards) do
|
||||
if Fk:getCardById(cid).name == "nullification" then
|
||||
table.insert(players, p)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- local use = {} ---@type CardUseStruct
|
||||
-- use.from = cardEffectEvent.to
|
||||
-- use.toCardId = cardEffectEvent.cardId
|
||||
-- use.responseToEvent = cardEffectEvent
|
||||
-- use.cardId = card
|
||||
-- self:useCard(use)
|
||||
local use = self:askForNullification(players)
|
||||
if use then
|
||||
use.toCardId = cardEffectEvent.cardId
|
||||
use.responseToEvent = cardEffectEvent
|
||||
self:useCard(use)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
---@field client_reply string
|
||||
---@field default_reply string
|
||||
---@field reply_ready boolean
|
||||
---@field reply_cancel boolean
|
||||
---@field phases Phase[]
|
||||
---@field phase_state table[]
|
||||
---@field phase_index integer
|
||||
|
@ -25,6 +26,7 @@ function ServerPlayer:initialize(_self)
|
|||
self.client_reply = ""
|
||||
self.default_reply = ""
|
||||
self.reply_ready = false
|
||||
self.reply_cancel = false
|
||||
self.phases = {}
|
||||
end
|
||||
|
||||
|
@ -44,6 +46,7 @@ function ServerPlayer:doRequest(command, jsonData, timeout)
|
|||
timeout = timeout or self.room.timeout
|
||||
self.client_reply = ""
|
||||
self.reply_ready = false
|
||||
self.reply_cancel = false
|
||||
self.serverplayer:doRequest(command, jsonData, timeout)
|
||||
end
|
||||
|
||||
|
@ -61,6 +64,10 @@ function ServerPlayer:waitForReply(timeout)
|
|||
end
|
||||
self.request_data = ""
|
||||
self.client_reply = result
|
||||
if result == "__cancel" then
|
||||
result = ""
|
||||
self.reply_cancel = true
|
||||
end
|
||||
if result ~= "" then self.reply_ready = true end
|
||||
return result
|
||||
end
|
||||
|
|
|
@ -77,6 +77,9 @@ extension:addCards({
|
|||
|
||||
local jinkSkill = fk.CreateActiveSkill{
|
||||
name = "jink_skill",
|
||||
can_use = function()
|
||||
return false
|
||||
end,
|
||||
on_effect = function(self, room, effect)
|
||||
if effect.responseToEvent then
|
||||
effect.responseToEvent.isCancellOut = true
|
||||
|
|
|
@ -22,6 +22,8 @@ Item {
|
|||
property alias dynamicCardArea: dynamicCardArea
|
||||
|
||||
property var selected_targets: []
|
||||
property string responding_card
|
||||
property bool respond_play: false
|
||||
|
||||
Image {
|
||||
source: AppPath + "/image/gamebg"
|
||||
|
@ -104,8 +106,8 @@ Item {
|
|||
from: "*"; to: "responding"
|
||||
ScriptAction {
|
||||
script: {
|
||||
dashboard.enableCards();
|
||||
dashboard.enableSkills();
|
||||
dashboard.enableCards(responding_card);
|
||||
dashboard.enableSkills(responding_card);
|
||||
progress.visible = true;
|
||||
okCancel.visible = true;
|
||||
}
|
||||
|
|
|
@ -111,7 +111,17 @@ RowLayout {
|
|||
}
|
||||
}
|
||||
|
||||
function enableCards() {
|
||||
// If cname is set, we are responding card.
|
||||
function enableCards(cname) {
|
||||
if (cname) {
|
||||
let ids = [], cards = handcardAreaItem.cards;
|
||||
for (let i = 0; i < cards.length; i++) {
|
||||
if (cards[i].name === cname)
|
||||
ids.push(cards[i].cid);
|
||||
}
|
||||
handcardAreaItem.enableCards(ids);
|
||||
return;
|
||||
}
|
||||
// TODO: expand pile
|
||||
let ids = [], cards = handcardAreaItem.cards;
|
||||
for (let i = 0; i < cards.length; i++) {
|
||||
|
@ -230,7 +240,11 @@ RowLayout {
|
|||
skillPanel.loseSkill(skill_name);
|
||||
}
|
||||
|
||||
function enableSkills() {
|
||||
function enableSkills(cname) {
|
||||
if (cname) {
|
||||
// TODO: vs skill
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < skillButtons.count; i++) {
|
||||
let item = skillButtons.itemAt(i);
|
||||
item.enabled = JSON.parse(Backend.callLuaFunction("ActiveCanUse", [item.orig]));
|
||||
|
|
|
@ -88,11 +88,11 @@ function doCancelButton() {
|
|||
dashboard.stopPending();
|
||||
dashboard.deactivateSkillButton();
|
||||
dashboard.unSelectAll();
|
||||
replyToServer("");
|
||||
replyToServer("__cancel");
|
||||
return;
|
||||
}
|
||||
|
||||
replyToServer("");
|
||||
replyToServer("__cancel");
|
||||
}
|
||||
|
||||
function replyToServer(jsonData) {
|
||||
|
@ -246,6 +246,12 @@ callbacks["AddPlayer"] = function(jsonData) {
|
|||
}
|
||||
|
||||
function enableTargets(card) { // card: int | { skill: string, subcards: int[] }
|
||||
if (roomScene.respond_play) {
|
||||
let candidate = (!isNaN(card) && card !== -1) || typeof(card) === "string";
|
||||
okButton.enabled = candidate;
|
||||
return;
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
let candidate = (!isNaN(card) && card !== -1) || typeof(card) === "string";
|
||||
let all_photos = [dashboard.self];
|
||||
|
@ -591,6 +597,7 @@ callbacks["AskForUseActiveSkill"] = function(jsonData) {
|
|||
}
|
||||
// TODO: process prompt
|
||||
|
||||
roomScene.respond_play = false;
|
||||
roomScene.state = "responding";
|
||||
dashboard.startPending(skill_name);
|
||||
cancelButton.enabled = cancelable;
|
||||
|
@ -603,3 +610,37 @@ callbacks["CancelRequest"] = function() {
|
|||
callbacks["GameLog"] = function(jsonData) {
|
||||
roomScene.addToLog(jsonData)
|
||||
}
|
||||
|
||||
callbacks["AskForUseCard"] = function(jsonData) {
|
||||
// jsonData: card, prompt, cancelable, {}
|
||||
let data = JSON.parse(jsonData);
|
||||
let cardname = data[0];
|
||||
let prompt = data[1];
|
||||
|
||||
roomScene.promptText = Backend.translate(prompt)
|
||||
.arg(Backend.translate(cardname));
|
||||
roomScene.responding_card = cardname;
|
||||
roomScene.respond_play = false;
|
||||
roomScene.state = "responding";
|
||||
okButton.enabled = false;
|
||||
cancelButton.enabled = true;
|
||||
}
|
||||
|
||||
callbacks["AskForResponseCard"] = function(jsonData) {
|
||||
// jsonData: card, prompt, cancelable, {}
|
||||
let data = JSON.parse(jsonData);
|
||||
let cardname = data[0];
|
||||
let prompt = data[1];
|
||||
|
||||
roomScene.promptText = Backend.translate(prompt)
|
||||
.arg(Backend.translate(cardname));
|
||||
roomScene.responding_card = cardname;
|
||||
roomScene.respond_play = true;
|
||||
roomScene.state = "responding";
|
||||
okButton.enabled = false;
|
||||
cancelButton.enabled = true;
|
||||
}
|
||||
|
||||
callbacks["WaitForNullification"] = function() {
|
||||
roomScene.state = "notactive";
|
||||
}
|
||||
|
|
|
@ -108,7 +108,8 @@ static int callback(void *jsonDoc, int argc, char **argv, char **cols) {
|
|||
|
||||
QJsonObject SelectFromDatabase(sqlite3 *db, const QString &sql) {
|
||||
QJsonObject obj;
|
||||
sqlite3_exec(db, sql.toUtf8().data(), callback, (void *)&obj, nullptr);
|
||||
auto bytes = sql.toUtf8();
|
||||
sqlite3_exec(db, bytes.data(), callback, (void *)&obj, nullptr);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -118,7 +119,8 @@ QString SelectFromDb(sqlite3 *db, const QString &sql) {
|
|||
}
|
||||
|
||||
void ExecSQL(sqlite3 *db, const QString &sql) {
|
||||
sqlite3_exec(db, sql.toUtf8().data(), nullptr, nullptr, nullptr);
|
||||
auto bytes = sql.toUtf8();
|
||||
sqlite3_exec(db, bytes.data(), nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void CloseDatabase(sqlite3 *db) {
|
||||
|
|
12
src/main.cpp
12
src/main.cpp
|
@ -44,23 +44,23 @@ static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath)
|
|||
|
||||
void fkMsgHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
|
||||
fprintf(stderr, "\r[%s] ", QTime::currentTime().toString("hh:mm:ss").toLatin1().constData());
|
||||
auto localMsg = msg.toUtf8().constData();
|
||||
auto localMsg = msg.toUtf8();
|
||||
auto threadName = QThread::currentThread()->objectName().toLatin1().constData();
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
fprintf(stderr, "[%s/\e[1;30mDEBUG\e[0m] %s\n", threadName, localMsg);
|
||||
fprintf(stderr, "[%s/\e[1;30mDEBUG\e[0m] %s\n", threadName, localMsg.constData());
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
fprintf(stderr, "[%s/\e[1;32mINFO\e[0m] %s\n", threadName, localMsg);
|
||||
fprintf(stderr, "[%s/\e[1;32mINFO\e[0m] %s\n", threadName, localMsg.constData());
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
fprintf(stderr, "[%s/\e[1;33mWARNING\e[0m] %s\n", threadName, localMsg);
|
||||
fprintf(stderr, "[%s/\e[1;33mWARNING\e[0m] %s\n", threadName, localMsg.constData());
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
fprintf(stderr, "[%s/\e[1;31mCRITICAL\e[0m] %s\n", threadName, localMsg);
|
||||
fprintf(stderr, "[%s/\e[1;31mCRITICAL\e[0m] %s\n", threadName, localMsg.constData());
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
fprintf(stderr, "[%s/\e[1;31mFATAL\e[0m] %s\n", threadName, localMsg);
|
||||
fprintf(stderr, "[%s/\e[1;31mFATAL\e[0m] %s\n", threadName, localMsg.constData());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ QString ServerPlayer::waitForReply(int timeout)
|
|||
QString ret;
|
||||
if (getState() != Player::Online) {
|
||||
QThread::sleep(1);
|
||||
ret = "";
|
||||
ret = "__cancel";
|
||||
} else {
|
||||
ret = router->waitForReply(timeout);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ const char *Shell::ColoredText(const char *input, Color color, TextType type) {
|
|||
header.append(QString::number(30 + color));
|
||||
header.append("m");
|
||||
header.append(str);
|
||||
return header.toUtf8().constData();
|
||||
auto bytes = header.toUtf8();
|
||||
return bytes.constData();
|
||||
}
|
||||
|
||||
void Shell::helpCommand(QStringList &) {
|
||||
|
@ -103,7 +104,8 @@ void Shell::run() {
|
|||
auto command_list = command.split(' ');
|
||||
auto func = handler_map[command_list.first()];
|
||||
if (!func) {
|
||||
qWarning("Unknown command \"%s\". Type \"help\" for hints.", command_list.first().toUtf8().constData());
|
||||
auto bytes = command_list.first().toUtf8();
|
||||
qWarning("Unknown command \"%s\". Type \"help\" for hints.", bytes.constData());
|
||||
} else {
|
||||
command_list.removeFirst();
|
||||
(this->*func)(command_list);
|
||||
|
|
|
@ -61,7 +61,8 @@ lua_createtable(L, $1.length(), 0);
|
|||
|
||||
for (int i = 0; i < $1.length(); i++) {
|
||||
QString str = $1.at(i);
|
||||
lua_pushstring(L, str.toUtf8().constData());
|
||||
auto bytes = str.toUtf8();
|
||||
lua_pushstring(L, bytes.constData());
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,8 @@ bool QmlBackend::isDir(const QString &file) {
|
|||
QString QmlBackend::translate(const QString &src) {
|
||||
lua_State *L = ClientInstance->getLuaState();
|
||||
lua_getglobal(L, "Translate");
|
||||
lua_pushstring(L, src.toUtf8().data());
|
||||
auto bytes = src.toUtf8();
|
||||
lua_pushstring(L, bytes.data());
|
||||
|
||||
int err = lua_pcall(L, 1, 1, 0);
|
||||
const char *result = lua_tostring(L, -1);
|
||||
|
@ -125,9 +126,11 @@ void QmlBackend::pushLuaValue(lua_State *L, QVariant v) {
|
|||
case QMetaType::Double:
|
||||
lua_pushnumber(L, v.toDouble());
|
||||
break;
|
||||
case QMetaType::QString:
|
||||
lua_pushstring(L, v.toString().toUtf8().data());
|
||||
case QMetaType::QString: {
|
||||
auto bytes = v.toString().toUtf8();
|
||||
lua_pushstring(L, bytes.data());
|
||||
break;
|
||||
}
|
||||
case QMetaType::QVariantList:
|
||||
lua_newtable(L);
|
||||
list = v.toList();
|
||||
|
|
Loading…
Reference in New Issue