From 06545727d9d88f3fd7663d50ad6e469a41899491 Mon Sep 17 00:00:00 2001 From: AlexanderAndersonAmenAmen <104784206+AlexanderAndersonAmenAmen@users.noreply.github.com> Date: Tue, 28 Jul 2026 20:07:16 +0300 Subject: [PATCH 1/2] Added 6 new MP Jokers (Line Cutter, Balloons, Occultist, Jester in Yellow, Last Laugh, Dynamic Duo) --- assets/1x/j_balloons.png | Bin 0 -> 2123 bytes assets/1x/j_dynamic_duo.png | Bin 0 -> 8512 bytes assets/1x/j_jester_in_yellow.png | Bin 0 -> 6079 bytes assets/1x/j_last_laugh.png | Bin 0 -> 4697 bytes assets/1x/j_line_cutter.png | Bin 0 -> 2464 bytes assets/1x/j_occultist.png | Bin 0 -> 3173 bytes assets/2x/j_balloons.png | Bin 0 -> 2669 bytes assets/2x/j_dynamic_duo.png | Bin 0 -> 10217 bytes assets/2x/j_jester_in_yellow.png | Bin 0 -> 6978 bytes assets/2x/j_last_laugh.png | Bin 0 -> 5472 bytes assets/2x/j_line_cutter.png | Bin 0 -> 2962 bytes assets/2x/j_occultist.png | Bin 0 -> 3768 bytes localization/en-us.lua | 64 +++++++++++ objects/jokers/_pvp_sell_utils.lua | 171 ++++++++++++++++++++++++++++ objects/jokers/balloons.lua | 56 +++++++++ objects/jokers/dynamic_duo.lua | 33 ++++++ objects/jokers/jester_in_yellow.lua | 33 ++++++ objects/jokers/last_laugh.lua | 33 ++++++ objects/jokers/line_cutter.lua | 20 ++++ objects/jokers/occultist.lua | 25 ++++ 20 files changed, 435 insertions(+) create mode 100644 assets/1x/j_balloons.png create mode 100644 assets/1x/j_dynamic_duo.png create mode 100644 assets/1x/j_jester_in_yellow.png create mode 100644 assets/1x/j_last_laugh.png create mode 100644 assets/1x/j_line_cutter.png create mode 100644 assets/1x/j_occultist.png create mode 100644 assets/2x/j_balloons.png create mode 100644 assets/2x/j_dynamic_duo.png create mode 100644 assets/2x/j_jester_in_yellow.png create mode 100644 assets/2x/j_last_laugh.png create mode 100644 assets/2x/j_line_cutter.png create mode 100644 assets/2x/j_occultist.png create mode 100644 objects/jokers/_pvp_sell_utils.lua create mode 100644 objects/jokers/balloons.lua create mode 100644 objects/jokers/dynamic_duo.lua create mode 100644 objects/jokers/jester_in_yellow.lua create mode 100644 objects/jokers/last_laugh.lua create mode 100644 objects/jokers/line_cutter.lua create mode 100644 objects/jokers/occultist.lua diff --git a/assets/1x/j_balloons.png b/assets/1x/j_balloons.png new file mode 100644 index 0000000000000000000000000000000000000000..4d543cc8ea0daee1f309397d35e1502f091f491c GIT binary patch literal 2123 zcmV-R2(Px-1xZ9fRCt{2olj^~M;yn$yNNvn2`PjYsvcz95RI3fwo-)lR1rLQiCzMM2%@CW zcq-x_@(1Z9O`$;%DlFupxp)x7TZJI%sh1>5a8a}rloex;T+(cMaA%$Uz2D6IX5PH) z+W3V)-n@CcGoSaJ-@KXk-YoD@M&$tD&wC31fUeFCEU&C?G`mpEQdeh3Zh2)D0Py|( zKD2B5HkMab@!dCjn^w4H>(2c}WsDpE4dV{Qlr(riFNk zuQL7o5RDgmff}HigL3UO(}xa5Rg&u5gGbim&OLaPI5q(%OL1WI0=X(+k_iZx$LBlp zL8S>01v6gkO;k!!Nh;rCeDZIKb10a>?rp}rk~16vF+`a=#}s4A<+AlS695}nsW{hi zO68m%i-!|wdO$aUDOJ`m*u4$qav6m}fz4xsXFJYEaMFbO%TX>x~F@71=m%_0tAcesJoy+;$WKOBMM(_jR%H=~y7#6A6T6AI z!O-GWcQFz(_2!2?pLqQFTF zMkxT0Nt|nxr0x;JF*T{QU^a&G*cj4^;Q`15$p*$pshkr73@afZs%Nj_fk7HLF~Q`n zR+AY#0EIx2G%eATMeMtj92k|xf@0M6;yIqQ?-Jw;SCDhkx<&_(h&j3}?g4<^|C*av z3~kySPb%t=+|_ErMa`D86tqc2>$Vv{tc#lHo=i`Xs;tckoLi)ECu>>Z#0tc&%If<= zz+~kfue%SDCgt1fD7A`PbQztqS*{Vu5qCl)nYzd<<|qfzn3Gjcltt5GOPba-oLgLh zxfPWtZ7eV}$hJ~UkBI85Lz1`?bq+bLJ|w45{jZ$klJBjVEd|F{ zshbt;o-=7i+8v2dh1~H>1S=Zs!H&!+1`gwVMhqdZ;nqQg>R>;cC)h#cQMXtsRo2*NqJ5r| zcJ@}(F>0HGqyULrlmQT_On}BotQL3W3WkD{FU>k#)VA+e&tm(FHmR6$HmmAje***) z5Kim!r?EbNI=pmEmUmZf3(O|X-#w1`yT`qcYqqR#E}R@|%q$4ZHYrFkK~2nU$Hd(B zXrHIcYxocX#3UWizHk4C_PH^Y`Pk~=n-ymsQ&3%+xq_a76Nz-)Dg93;**r1ij5)Mv z#n!c-e+xdg|LJ73a;z@DPNZe(9Eod8GPy>V+P^e&rD5A9Zlr$c@k=(ZsJ9AnPZ}^T zojvfjp(*wZoIuaOi8>^cOe6JEUw+2s7dz*|$uZ;f1yx!w64yv1T}q}=9-I`+#?Q3^q&;s*`55Cq+rt1<=m zR^!E9;KpqLz`~J((F&xb2Us15DIV4H7pJ_xD`>LIBzkuGZrt_;B#AdR2z1|gu@@*# z;pp%P0O0!cJ4k9>skmg?a~`LZL8@4v#dX*=7d4;7Aq|Q;^^Q zwQ%HMLtb4Wi-43WYYj_WnE+fI8OG7!5nLP@c7A52SIAOOoI(L1V6NCCF&xu6Ss@zR zvB#_JQ_-to8h`W&cD1d>PJiE=#m>XB*##>cJuc{HBFzFrV>{&Ub=#KabamLk^~uGh9{V00;TF(MrdbqyVGPLg`CaBP8>Ldt5*t{5?c zbBvFI*UyOwMFQf?)O5qPty!goqQt_HERUI1*Qci%x>PQR!ZKIGrN@GzWOPnFpj95# z3vC0%oqgBBL>EVfab{||UO{@Z%{FzRkGrJ3&(6dBiMV6yy+mEP$w_pTMjERm3lni; zD9Oy8atW=ltE*P|^=*^H*E!rmtG4^jTu?XNmkxoVORuoRMNzJEI7wGt3R%m`1Vs`{ zq!sp2VzO(qR;iX~b@_GlAZya(5Bn2oIRN-;;Ys4>4YsQ8++RdjXGiYqzTNMfqkcl< z&V9N**VdA%zv7|CoLpCDhyIfyTTc3K&3u$Y{{aaPSaFEpdWrx5002ovPDHLkV1jN} B1*!l5 literal 0 HcmV?d00001 diff --git a/assets/1x/j_dynamic_duo.png b/assets/1x/j_dynamic_duo.png new file mode 100644 index 0000000000000000000000000000000000000000..5c4b883d0ef2334043ae1ff5d713cf3f7dfe0eec GIT binary patch literal 8512 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 FV1h_kzpMZN literal 0 HcmV?d00001 diff --git a/assets/1x/j_last_laugh.png b/assets/1x/j_last_laugh.png new file mode 100644 index 0000000000000000000000000000000000000000..1e3b5c3ebf8b654ae810fbab8cbe0cd3a4977631 GIT binary patch literal 4697 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 LNkvXXu0mjfe=!fo literal 0 HcmV?d00001 diff --git a/assets/2x/j_balloons.png b/assets/2x/j_balloons.png new file mode 100644 index 0000000000000000000000000000000000000000..d923934f8298bf6bdddb75e24d26353c4c36d55d GIT binary patch literal 2669 zcmX9=dpwi-A9qe2M=r%d3=tJhmNd7y4lPB@CFBx9j2Rjy*YG3Z9HZmTFyua?P#8v$ z>&(&&LsVmxx#WH+{GN6Gc%J9=`aa+9`*V4}KcCO{Z)?PLA$}=-9v&Vcvm0<*;F|_K zoqW8&o0X(p0epT5vAu4>Q$Hf}m4}C4$qa667hbqrWLfRX03~*1RzI>f;V(6bqS75@l96qPSID=xrD7pwCvhnk6tU9;wcjv{o0-#8t!wJD6JhfTF{aR$m-J{OOVE3az7ECYH5f0zpWL|=V1v;%wCZZ#%-pA73*X{f* z`0A^=M0XIbclR)MM{AG77E@i}9baPk?X3`L`+7#(nXTHmd*VSndP&sXNx1~05vK704IOKA)l zay6joMIr#vq>WgCQup`Ul9P#bb;h*Z0+2O5g5?@83O)X`0233vSy~?2kj}Y7FKpYa z8#sNeggv?({HJD-b_L^f>eaJ2kP<^}JhWntijrMuod=ztG0Ytueq;i8vDjy9DcTct z{>9kYnu8=pwm04}XB{GrV~7Fiuv1TK@dGYctYrAdf@1V!K-$P-r zN%j(-|4J2ONy~giX?Dom+_%K8Y=H}l0x1!tP`6LCKX!DmMS&C(fGAe__P)GZABItN z$(HJoFYV2jG1Zb9C*zd05KuSK0;=o<$|j-Nts`9G#e0Dy!;m?NQ$Rv~kyg@zENOaT zM=BhBREo;Xe$&J3cWgdUll=hLaAiiE6o~}wt?cB&M5$%fao`PQkL@*CT8$83 zBk>9%jGmwYu~MyJD!$RMjdda@iDcB^R79*9-&HnYMh ziK}2LwD;UAc+71Kc+@0=hg?Bwe$kb zGW{5iPzldD_H}5f4?|=wPp)b9WEPzWqxbvADD~llFmgO@*!usG!QMgn8Lpp=2*G zjA{UNJe`D+?6a~TBvz#R;oDccv|WSpO$RkC0>^kVRfV-`bECY2K$m^5gbY5Zb_eQHLFLxLiw&@dKFk zDRgkE%JnmEAT;O2S#Qkay$z`!Tjux?T@N8R1JP0 zBpl5?ASV8Bb8UWYqbvORR=rUI`-I%7!81q9@uSh(H$$~SZs{o+rTG}*>SB+!pdB!e zSlZRb#AU4`D{YGnN);YYJo=DY6W6^Z?-6yG%iMcFO0Pc-F@LYK?N|XLMP?6rAy{v* z06G68w{!n;eZ*!)S&}46b_ zzf4qta`rge2IbxYmEfvIT4`8|w3AHiy$Nf*S^lXt@f!M#&K`Ub!mS5k5YSB3Zs?jDGOTD?XyAxf;p1wMSM>K-tK!SQ1IcJi z^-AqX^TNSvEcb7QH_`c!iVf(7e^Vdp(n ztYKqH@Oqq=*)l+E!&~>m$U^}U5z@nj#l+-+gPoc8n3e(MLf|q4ho4-UYY`UN`}$E2 z?kf}Dn2%9)C+Rwsu4>?rVNaiR{m}{ILJ$bf1M7O0_x47neaW}VVK_e%Zp#F2YOnWT Z&vj!|LoSLW0QW~8vug-=y~*A9{{yi{Eo=Y) literal 0 HcmV?d00001 diff --git a/assets/2x/j_dynamic_duo.png b/assets/2x/j_dynamic_duo.png new file mode 100644 index 0000000000000000000000000000000000000000..369e2c4909b161a6bb712cf55438f1d68b6515bf GIT binary patch literal 10217 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 DKXfNt literal 0 HcmV?d00001 diff --git a/assets/2x/j_jester_in_yellow.png b/assets/2x/j_jester_in_yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..bf2918fdea7017b84d2e2c6c002653a564728cf3 GIT binary patch literal 6978 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 Ld9~u-`%nG{e)kDj literal 0 HcmV?d00001 diff --git a/assets/2x/j_last_laugh.png b/assets/2x/j_last_laugh.png new file mode 100644 index 0000000000000000000000000000000000000000..5ab29b9802e5cfec55f6b59d52fcef63aebe47a0 GIT binary patch literal 5472 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 BA4mWI literal 0 HcmV?d00001 diff --git a/assets/2x/j_line_cutter.png b/assets/2x/j_line_cutter.png new file mode 100644 index 0000000000000000000000000000000000000000..b9b3a0657527f80c8e1ddf3f54642f78309beb4e GIT binary patch literal 2962 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 Z;2dF{#?%^`QAvOZvaz(cs5kSu_dkXjsP+H= literal 0 HcmV?d00001 diff --git a/assets/2x/j_occultist.png b/assets/2x/j_occultist.png new file mode 100644 index 0000000000000000000000000000000000000000..54599592af96b887190c8e5cfc227426c8b9f024 GIT binary patch literal 3768 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 literal 0 HcmV?d00001 diff --git a/localization/en-us.lua b/localization/en-us.lua index 8ce7d1df..5ea4b007 100644 --- a/localization/en-us.lua +++ b/localization/en-us.lua @@ -234,6 +234,70 @@ return { "not in a {C:attention}PvP Blind{}", }, }, + j_mp_last_laugh = { + name = "Last Laugh", + text = { + "Sell this card during", + "{C:attention}PvP Blind{} to destroy {C:attention}#1#{}", + "random cards in hand", + }, + }, + j_mp_line_cutter = { + name = "Line Cutter", + text = { + "Sell this card during", + "{C:attention}PvP Blind{} to create", + "a {C:attention}Voucher Tag{}", + }, + }, + j_mp_balloons = { + name = "Balloons", + text = { + "Sell this card during", + "{C:attention}PvP Blind{} to create a", + "random {C:attention}Tag{} for each", + "empty Joker slot", + "{C:inactive}(Max of {C:attention}#1#{} {C:inactive}Tags)", + }, + }, + j_mp_occultist = { + name = "Occultist", + text = { + "Sell this card during", + "{C:attention}PvP Blind{} to create a", + "{C:attention}Charm Tag{} for each", + "empty Joker slot", + "{C:inactive}(Max of {C:attention}#1#{} {C:inactive}Tags)", + }, + }, + j_mp_jester_in_yellow = { + name = "Jester in Yellow", + text = { + "Sell this card during", + "{C:attention}PvP Blind{} to add", + "{C:money}Rental{} to a random", + "{X:purple,C:white}Nemesis{} Joker", + }, + }, + j_mp_dynamic_duo = { + name = "Dynamic Duo", + text = { + "Sell this card during", + "{C:attention}PvP Blind{} to remove", + "{C:dark_edition}Editions{} and {C:attention}Stickers{}", + "from players' Jokers", + }, + }, + j_mp_dynamic_duo_overflow = { + name = "Dynamic Duo", + text = { + "Sell this card during", + "{C:attention}PvP Blind{} to remove", + "{C:dark_edition}Editions{} and {C:attention}Stickers{}", + "from players' Jokers", + "{C:inactive}(Cards can overflow)", + }, + }, j_mp_hanging_chad = { name = "Hanging Chad", text = { diff --git a/objects/jokers/_pvp_sell_utils.lua b/objects/jokers/_pvp_sell_utils.lua new file mode 100644 index 00000000..d7463467 --- /dev/null +++ b/objects/jokers/_pvp_sell_utils.lua @@ -0,0 +1,171 @@ +MP.PVP_SELL = MP.PVP_SELL or { handlers = {} } + +function MP.PVP_SELL.is_active() + return G and G.STAGE == G.STAGES.RUN and MP.is_pvp_boss() +end + +function MP.PVP_SELL.register(center_key, handler) + MP.PVP_SELL.handlers[center_key] = handler +end + +function MP.PVP_SELL.empty_joker_slots_after_sale(card) + if not (G and G.jokers and G.jokers.config and G.jokers.cards) then return 0 end + local joker_count = #G.jokers.cards + if card and card.area == G.jokers then joker_count = math.max(0, joker_count - 1) end + return math.max((G.jokers.config.card_limit or 0) - joker_count, 0) +end + +function MP.PVP_SELL.random_hand_cards(count, seed) + local picked = {} + if not (G and G.hand and G.hand.cards and #G.hand.cards > 0) then return picked end + local candidates = {} + for _, hand_card in ipairs(G.hand.cards) do candidates[#candidates + 1] = hand_card end + pseudoshuffle(candidates, pseudoseed(seed or "mp_pvp_sell_hand")) + for i = 1, math.min(count or 0, #candidates) do picked[#picked + 1] = candidates[i] end + return picked +end + +function MP.PVP_SELL.add_tag_with_sfx(tag_key) + add_tag(Tag(tag_key)) + play_sound("generic1", 0.9 + math.random() * 0.1, 0.8) + play_sound("holo1", 1.2 + math.random() * 0.1, 0.4) +end + +function MP.PVP_SELL.apply_rental(card) + if not card or card.REMOVED then return false end + card.ability = card.ability or {} + if card.ability.rental then return false end + if card.set_rental then + card:set_rental(true) + else + card.ability.rental = true + if card.set_cost then card:set_cost() end + end + card:juice_up(0.4, 0.5) + return true +end + +function MP.PVP_SELL.clear_editions_and_stickers(card) + if not card or card.REMOVED then return false end + local changed = false + + if card.edition then + if card.edition.type == "mp_phantom" and remove_phantom then remove_phantom(card) end + card:set_edition(nil, true, true) + changed = true + end + + card.ability = card.ability or {} + if card.ability.eternal then + if card.set_eternal then card:set_eternal(false) else card.ability.eternal = false end + changed = true + end + if card.ability.perishable or card.ability.perish_tally ~= nil + or card.ability.perishable_tally ~= nil or card.ability.perishable_rounds ~= nil then + -- Steamodded's Perishable sticker keeps its countdown in perish_tally. + -- Clear through the registered sticker first, then force-reset every + -- vanilla field so the badge/effect cannot survive on either client. + local perishable_sticker = SMODS.Stickers and SMODS.Stickers.perishable + if perishable_sticker and perishable_sticker.apply then + perishable_sticker:apply(card, false) + end + if card.set_perishable then card:set_perishable(false) end + card.ability.perishable = nil + card.ability.perish_tally = nil + card.ability.perishable_tally = nil + card.ability.perishable_rounds = nil + changed = true + end + if card.ability.rental then + if card.set_rental then card:set_rental(false) else card.ability.rental = false end + changed = true + end + + for _, key in ipairs({ + "mp_sticker_balanced", + "mp_sticker_extra_credit", + "mp_sticker_persistent", + "mp_sticker_unreliable", + "mp_sticker_draining", + "mp_sticker_nemesis", + }) do + if card.ability[key] then + local sticker = SMODS.Stickers and SMODS.Stickers[key] + if sticker and sticker.apply then sticker:apply(card, false) else card.ability[key] = false end + changed = true + end + end + + if changed then + if card.set_cost then card:set_cost() end + card:juice_up(0.25, 0.25) + end + return changed +end + +function MP.PVP_SELL.clear_area(area, excluded_card) + local changed = 0 + if area and area.cards then + for _, joker in ipairs(area.cards) do + if joker ~= excluded_card and MP.PVP_SELL.clear_editions_and_stickers(joker) then changed = changed + 1 end + end + end + return changed +end + +function MP.PVP_SELL.clear_nemesis_display_stickers() + local changed = 0 + if not (MP.shared and MP.shared.cards) then return changed end + for _, joker in ipairs(MP.shared.cards) do + if joker and joker.ability then + if joker.ability.rental then + if joker.set_rental then joker:set_rental(false) else joker.ability.rental = false end + changed = changed + 1 + end + -- Keep the Phantom edition/Nemesis marker: those identify the opponent's + -- display copy and are not actual modifiers on their owned Joker. + end + end + return changed +end + +local function apply_jester_rental_to_area(area, requested_index) + if not (area and area.cards and #area.cards > 0) then return false end + local target = requested_index and area.cards[requested_index] or nil + if target and not (target.ability and target.ability.rental) then return MP.PVP_SELL.apply_rental(target) end + local candidates = {} + for _, joker in ipairs(area.cards) do + if joker and not joker.REMOVED and not (joker.ability and joker.ability.rental) then candidates[#candidates + 1] = joker end + end + if #candidates < 1 then return false end + return MP.PVP_SELL.apply_rental(pseudorandom_element(candidates, pseudoseed("j_mp_jester_in_yellow_receive"))) +end + +MP.register_mod_action("pvp_jester_rental", function(payload) + apply_jester_rental_to_area(G.jokers, tonumber(payload and payload.index)) +end) + +MP.register_mod_action("pvp_dynamic_duo", function() + MP.PVP_SELL.clear_area(G.jokers) +end) + +function MP.PVP_SELL.send_to_nemesis(action, params) + if MP.LOBBY and MP.LOBBY.code and MP.ACTIONS and MP.ACTIONS.modded then + MP.ACTIONS.modded(MP.id or "Multiplayer", action, params) + end +end + +local sell_card_ref = Card.sell_card +function Card:sell_card(...) + local center_key = self.config and self.config.center and self.config.center.key + local handler = center_key and MP.PVP_SELL.handlers[center_key] + if handler and not self.mp_pvp_sell_triggered and MP.PVP_SELL.is_active() then + self.mp_pvp_sell_triggered = true + local ok, err = pcall(handler, self) + if not ok then + self.mp_pvp_sell_triggered = nil + sendErrorMessage("PvP sell Joker failed (" .. tostring(center_key) .. "): " .. tostring(err), "MULTIPLAYER") + end + end + return sell_card_ref(self, ...) +end diff --git a/objects/jokers/balloons.lua b/objects/jokers/balloons.lua new file mode 100644 index 00000000..7d51d463 --- /dev/null +++ b/objects/jokers/balloons.lua @@ -0,0 +1,56 @@ +SMODS.Atlas({ key = "balloons", path = "j_balloons.png", px = 71, py = 95 }) + +SMODS.Joker({ + key = "balloons", atlas = "balloons", rarity = 2, cost = 6, + unlocked = true, discovered = true, blueprint_compat = false, + eternal_compat = false, perishable_compat = true, + config = { extra = { max_tags = 3 } }, + loc_vars = function(self, info_queue, card) return { vars = { card.ability.extra.max_tags } } end, + mp_include = function(self) + return MP.LOBBY.code and MP.LOBBY.config.multiplayer_jokers and not MP.is_layer_active("sandbox") + end, + mp_credits = { art = { "Kars" } }, +}) + +local BALLOONS_VANILLA_TAGS = { + "tag_uncommon", + "tag_foil", + "tag_holo", + "tag_polychrome", + "tag_voucher", + "tag_standard", + "tag_charm", + "tag_meteor", + "tag_buffoon", + "tag_handy", + "tag_garbage", + "tag_ethereal", + "tag_coupon", + "tag_double", + "tag_d_six", + "tag_top_up", + "tag_skip", + "tag_orbital", + "tag_economy", +} + +MP.PVP_SELL.register("j_mp_balloons", function(card) + local count = math.min(card.ability.extra.max_tags, MP.PVP_SELL.empty_joker_slots_after_sale(card)) + if count < 1 then + card_eval_status_text(card, "extra", nil, nil, nil, { message = "No empty slots", colour = G.C.RED }) + return + end + local pool = {} + for _, tag_key in ipairs(BALLOONS_VANILLA_TAGS) do + -- Exact whitelist: custom Multiplayer/modded Tags can never enter the pool. + if G.P_TAGS and G.P_TAGS[tag_key] then pool[#pool + 1] = tag_key end + end + if #pool < 1 then return end + for i = 1, count do + local tag_key = pseudorandom_element(pool, pseudoseed("j_mp_balloons_" .. tostring(i))) + MP.PVP_SELL.add_tag_with_sfx(tag_key) + end + card_eval_status_text(card, "extra", nil, nil, nil, { + message = "+" .. tostring(count) .. " Tag" .. (count == 1 and "" or "s"), colour = G.C.FILTER, + }) +end) diff --git a/objects/jokers/dynamic_duo.lua b/objects/jokers/dynamic_duo.lua new file mode 100644 index 00000000..7a700594 --- /dev/null +++ b/objects/jokers/dynamic_duo.lua @@ -0,0 +1,33 @@ +SMODS.Atlas({ key = "dynamic_duo", path = "j_dynamic_duo.png", px = 71, py = 95 }) + +SMODS.Joker({ + key = "dynamic_duo", atlas = "dynamic_duo", rarity = 2, cost = 5, + unlocked = true, discovered = true, blueprint_compat = false, + eternal_compat = false, perishable_compat = true, + loc_vars = function(self, info_queue, card) + local has_negative = false + if G and G.jokers and G.jokers.cards then + for _, joker in ipairs(G.jokers.cards) do + if joker and joker.edition + and (joker.edition.negative or joker.edition.type == "negative") then + has_negative = true + break + end + end + end + return { key = has_negative and "j_mp_dynamic_duo_overflow" or "j_mp_dynamic_duo" } + end, + mp_include = function(self) + return MP.LOBBY.code and MP.LOBBY.config.multiplayer_jokers and not MP.is_layer_active("sandbox") + end, + mp_credits = { art = { "Kars" } }, +}) + +MP.PVP_SELL.register("j_mp_dynamic_duo", function(card) + local changed = MP.PVP_SELL.clear_area(G.jokers, card) + changed = changed + MP.PVP_SELL.clear_nemesis_display_stickers() + MP.PVP_SELL.send_to_nemesis("pvp_dynamic_duo") + card_eval_status_text(card, "extra", nil, nil, nil, { + message = changed > 0 and "Stripped!" or "No modifiers", colour = changed > 0 and G.C.FILTER or G.C.RED, + }) +end) diff --git a/objects/jokers/jester_in_yellow.lua b/objects/jokers/jester_in_yellow.lua new file mode 100644 index 00000000..bccd080d --- /dev/null +++ b/objects/jokers/jester_in_yellow.lua @@ -0,0 +1,33 @@ +SMODS.Atlas({ key = "jester_in_yellow", path = "j_jester_in_yellow.png", px = 71, py = 95 }) + +SMODS.Joker({ + key = "jester_in_yellow", atlas = "jester_in_yellow", rarity = 2, cost = 4, + unlocked = true, discovered = true, blueprint_compat = false, + eternal_compat = false, perishable_compat = true, + mp_include = function(self) + return MP.LOBBY.code and MP.LOBBY.config.multiplayer_jokers and not MP.is_layer_active("sandbox") + end, + mp_credits = { art = { "Kars" } }, +}) + +MP.PVP_SELL.register("j_mp_jester_in_yellow", function(card) + local area = MP.shared + if not (area and area.cards and #area.cards > 0) then + card_eval_status_text(card, "extra", nil, nil, nil, { message = "No Nemesis Joker", colour = G.C.RED }) + return + end + local candidates = {} + for i, joker in ipairs(area.cards) do + if joker and not joker.REMOVED and not (joker.ability and joker.ability.rental) then + candidates[#candidates + 1] = { index = i, card = joker } + end + end + if #candidates < 1 then + card_eval_status_text(card, "extra", nil, nil, nil, { message = "Already Rental", colour = G.C.RED }) + return + end + local selected = pseudorandom_element(candidates, pseudoseed("j_mp_jester_in_yellow")) + MP.PVP_SELL.apply_rental(selected.card) + MP.PVP_SELL.send_to_nemesis("pvp_jester_rental", { index = selected.index }) + card_eval_status_text(card, "extra", nil, nil, nil, { message = "Rental!", colour = G.C.MONEY }) +end) diff --git a/objects/jokers/last_laugh.lua b/objects/jokers/last_laugh.lua new file mode 100644 index 00000000..ac7b8ac1 --- /dev/null +++ b/objects/jokers/last_laugh.lua @@ -0,0 +1,33 @@ +SMODS.Atlas({ key = "last_laugh", path = "j_last_laugh.png", px = 71, py = 95 }) + +SMODS.Joker({ + key = "last_laugh", atlas = "last_laugh", rarity = 2, cost = 5, + unlocked = true, discovered = true, blueprint_compat = false, + eternal_compat = false, perishable_compat = true, + config = { extra = { destroy = 5 } }, + loc_vars = function(self, info_queue, card) return { vars = { card.ability.extra.destroy } } end, + mp_include = function(self) + return MP.LOBBY.code and MP.LOBBY.config.multiplayer_jokers and not MP.is_layer_active("sandbox") + end, + mp_credits = { art = { "Kars" } }, +}) + +MP.PVP_SELL.register("j_mp_last_laugh", function(card) + local targets = MP.PVP_SELL.random_hand_cards(card.ability.extra.destroy, "j_mp_last_laugh") + if #targets < 1 then + card_eval_status_text(card, "extra", nil, nil, nil, { message = "No cards", colour = G.C.RED }) + return + end + for _, target in ipairs(targets) do + G.E_MANAGER:add_event(Event({ func = function() + if target and not target.destroyed then + play_sound("tarot1") + target.T.r = -0.2 + target:juice_up(0.3, 0.4) + end + return true + end })) + end + SMODS.destroy_cards(targets) + card_eval_status_text(card, "extra", nil, nil, nil, { message = "Destroyed " .. tostring(#targets), colour = G.C.RED }) +end) diff --git a/objects/jokers/line_cutter.lua b/objects/jokers/line_cutter.lua new file mode 100644 index 00000000..e2c18aef --- /dev/null +++ b/objects/jokers/line_cutter.lua @@ -0,0 +1,20 @@ +SMODS.Atlas({ key = "line_cutter", path = "j_line_cutter.png", px = 71, py = 95 }) + +SMODS.Joker({ + key = "line_cutter", atlas = "line_cutter", rarity = 2, cost = 4, + unlocked = true, discovered = true, blueprint_compat = false, + eternal_compat = false, perishable_compat = true, + loc_vars = function(self, info_queue, card) + info_queue[#info_queue + 1] = { key = "tag_voucher", set = "Tag" } + return { vars = {} } + end, + mp_include = function(self) + return MP.LOBBY.code and MP.LOBBY.config.multiplayer_jokers and not MP.is_layer_active("sandbox") + end, + mp_credits = { art = { "Kars" }}, +}) + +MP.PVP_SELL.register("j_mp_line_cutter", function(card) + MP.PVP_SELL.add_tag_with_sfx("tag_voucher") + card_eval_status_text(card, "extra", nil, nil, nil, { message = "+1 Voucher Tag!", colour = G.C.FILTER }) +end) diff --git a/objects/jokers/occultist.lua b/objects/jokers/occultist.lua new file mode 100644 index 00000000..416f544d --- /dev/null +++ b/objects/jokers/occultist.lua @@ -0,0 +1,25 @@ +SMODS.Atlas({ key = "occultist", path = "j_occultist.png", px = 71, py = 95 }) + +SMODS.Joker({ + key = "occultist", atlas = "occultist", rarity = 2, cost = 6, + unlocked = true, discovered = true, blueprint_compat = false, + eternal_compat = false, perishable_compat = true, + config = { extra = { max_tags = 3 } }, + loc_vars = function(self, info_queue, card) + info_queue[#info_queue + 1] = { key = "tag_charm", set = "Tag" } + return { vars = { card.ability.extra.max_tags } } + end, + mp_include = function(self) + return MP.LOBBY.code and MP.LOBBY.config.multiplayer_jokers and not MP.is_layer_active("sandbox") + end, + mp_credits = { art = { "Kars" } }, +}) + +MP.PVP_SELL.register("j_mp_occultist", function(card) + local count = math.min(card.ability.extra.max_tags, MP.PVP_SELL.empty_joker_slots_after_sale(card)) + for i = 1, count do MP.PVP_SELL.add_tag_with_sfx("tag_charm") end + card_eval_status_text(card, "extra", nil, nil, nil, { + message = count > 0 and ("+" .. tostring(count) .. " Charm Tag" .. (count == 1 and "" or "s")) or "No empty slots", + colour = count > 0 and G.C.FILTER or G.C.RED, + }) +end) From f38e0efdc13189f71b44ddf3cedba9c42c09748a Mon Sep 17 00:00:00 2001 From: AlexanderAndersonAmenAmen <104784206+AlexanderAndersonAmenAmen@users.noreply.github.com> Date: Tue, 28 Jul 2026 20:39:39 +0300 Subject: [PATCH 2/2] Phantom area display added for new Jokers --- objects/jokers/_pvp_sell_utils.lua | 36 +++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/objects/jokers/_pvp_sell_utils.lua b/objects/jokers/_pvp_sell_utils.lua index d7463467..052ba46e 100644 --- a/objects/jokers/_pvp_sell_utils.lua +++ b/objects/jokers/_pvp_sell_utils.lua @@ -8,6 +8,30 @@ function MP.PVP_SELL.register(center_key, handler) MP.PVP_SELL.handlers[center_key] = handler end +local function sold_phantom_queue() + MP.GAME = MP.GAME or {} + MP.GAME.pvp_sold_phantom_keys = MP.GAME.pvp_sold_phantom_keys or {} + return MP.GAME.pvp_sold_phantom_keys +end + +function MP.PVP_SELL.show_sold_phantom(center_key) + if not center_key or not (MP.LOBBY and MP.LOBBY.code) then return end + if not (MP.ACTIONS and MP.ACTIONS.send_phantom) then return end + table.insert(sold_phantom_queue(), center_key) + MP.ACTIONS.send_phantom(center_key) +end + +function MP.PVP_SELL.clear_sold_phantoms() + local queue = sold_phantom_queue() + if #queue < 1 then return end + if MP.LOBBY and MP.LOBBY.code and MP.ACTIONS and MP.ACTIONS.remove_phantom then + for _, center_key in ipairs(queue) do + MP.ACTIONS.remove_phantom(center_key) + end + end + MP.GAME.pvp_sold_phantom_keys = {} +end + function MP.PVP_SELL.empty_joker_slots_after_sale(card) if not (G and G.jokers and G.jokers.config and G.jokers.cards) then return 0 end local joker_count = #G.jokers.cards @@ -161,11 +185,21 @@ function Card:sell_card(...) local handler = center_key and MP.PVP_SELL.handlers[center_key] if handler and not self.mp_pvp_sell_triggered and MP.PVP_SELL.is_active() then self.mp_pvp_sell_triggered = true + -- These six Jokers remain visible to the opponent as Phantom copies for + -- the rest of this PvP Blind, even though the original card was sold. + MP.PVP_SELL.show_sold_phantom(center_key) local ok, err = pcall(handler, self) if not ok then - self.mp_pvp_sell_triggered = nil sendErrorMessage("PvP sell Joker failed (" .. tostring(center_key) .. "): " .. tostring(err), "MULTIPLAYER") end end return sell_card_ref(self, ...) end + +-- Cash Out is the lifetime boundary for sold PvP Joker Phantoms. Sending one +-- removal per queued sale also handles multiple copies of the same Joker. +local cash_out_ref = G.FUNCS.cash_out +function G.FUNCS.cash_out(...) + MP.PVP_SELL.clear_sold_phantoms() + return cash_out_ref(...) +end