@@ -6,9 +6,35 @@ import { cardEmotes, cards, colors, SelectIDs, uniqueVariants, variants } from "
66import { config } from "../index.js" ;
77import timeouts from "../timeouts.js" ;
88import { Card , UnoGame } from "../types.js" ;
9- import { getUsername , next , PickCardSelect , toTitleCase , wasLastTurnBlocked } from "../utils.js" ;
9+ import { getUsername , next , PickCardSelect , toTitleCase , updateStats , wasLastTurnBlocked } from "../utils.js" ;
1010import { games , onTimeout , sendGameMessage } from "./index.js" ;
1111
12+ function isSabotage ( ctx : ComponentInteraction < ComponentTypes . STRING_SELECT > , game : UnoGame < true > ) : boolean {
13+ // first card is duration=0, second is duration=1, etc
14+ let maxDuration = 4 ; // so default is kick on 5th card drawn
15+ if ( game . cards [ next ( game . players , game . players . indexOf ( game . lastPlayer . id ) ) ] . length <= 2 ) maxDuration -- ;
16+ if ( game . saboteurs [ game . lastPlayer . id ] ) maxDuration -- ;
17+
18+ if ( game . lastPlayer . duration >= maxDuration ) {
19+ game . players . splice ( game . players . indexOf ( ctx . member . id ) , 1 ) ;
20+ sendMessage ( ctx . channel . id , `Removed **${ getUsername ( game . lastPlayer . id , true , ctx . guild ) } ** for attempting to sabotage the game` ) ;
21+ if ( game . players . length <= 1 ) {
22+ updateStats ( game , game . players [ 0 ] ) ;
23+ return true ;
24+ }
25+
26+ game . currentPlayer = next ( game . players , game . players . indexOf ( game . currentPlayer ) ) ;
27+ game . lastPlayer . duration = 0 ;
28+ return true ;
29+ }
30+
31+ if ( game . lastPlayer . duration === maxDuration - 1 ) {
32+ game . saboteurs [ game . lastPlayer . id ] = true ;
33+ }
34+
35+ return false ;
36+ }
37+
1238export function onColorPlayed ( ctx : ComponentInteraction < ComponentTypes . STRING_SELECT > , game : UnoGame < true > ) {
1339 const { currentPlayer } = game ;
1440 if ( currentPlayer !== ctx . member . id ) return ;
@@ -117,32 +143,25 @@ export function onCardPlayed(ctx: ComponentInteraction<ComponentTypes.STRING_SEL
117143
118144 let extraInfo = "" ;
119145 if ( cardPlayed === "draw" ) {
120- if ( game . lastPlayer . duration >= 4 && game . settings . antiSabotage ) {
121- game . players . splice ( game . players . indexOf ( ctx . member . id ) , 1 ) ;
122- sendMessage ( ctx . channel . id , `Removed **${ getUsername ( game . lastPlayer . id , true , ctx . guild ) } ** for attempting to sabotage the game` ) ;
123- if ( game . players . length <= 1 ) return ;
124- game . currentPlayer = next ( game . players , game . players . indexOf ( game . currentPlayer ) ) ;
125- game . lastPlayer . duration = 0 ;
146+ if ( isSabotage ( ctx , game ) ) return ;
126147
127- return sendGameMessage ( game ) ;
128- } else {
129- const { cards : newCards , newDeck } = game . draw ( 1 ) ;
130- game . cards [ ctx . member . id ] . push ( newCards [ 0 ] ) ;
131- game . cards [ ctx . member . id ] . sort ( ( a , b ) => cards . indexOf ( a ) - cards . indexOf ( b ) ) ;
132- game . deck = newDeck ;
133- if ( game . settings . allowSkipping ) {
134- const components = PickCardSelect ( game , ctx . member . id ) ;
135- if ( components ) ctx . editOriginal ( {
136- content : config . emoteless
137- ? `You drew a ${ cardEmotes [ newCards [ 0 ] ] } ${ toTitleCase ( newCards [ 0 ] ) } `
138- : `${ game . cards [ ctx . member . id ] . map ( c => cardEmotes [ c ] ) . join ( " " ) }
148+ const { cards : newCards , newDeck } = game . draw ( 1 ) ;
149+ game . cards [ ctx . member . id ] . push ( newCards [ 0 ] ) ;
150+ game . cards [ ctx . member . id ] . sort ( ( a , b ) => cards . indexOf ( a ) - cards . indexOf ( b ) ) ;
151+ game . deck = newDeck ;
152+
153+ if ( game . settings . allowSkipping ) {
154+ const components = PickCardSelect ( game , ctx . member . id ) ;
155+ if ( components ) ctx . editOriginal ( {
156+ content : config . emoteless
157+ ? `You drew a ${ cardEmotes [ newCards [ 0 ] ] } ${ toTitleCase ( newCards [ 0 ] ) } `
158+ : `${ game . cards [ ctx . member . id ] . map ( c => cardEmotes [ c ] ) . join ( " " ) }
139159You drew ${ cardEmotes [ newCards [ 0 ] ] } ` ,
140- components
141- } ) ;
142- }
143- else
144- ctx . deleteOriginal ( ) ;
160+ components
161+ } ) ;
145162 }
163+ else
164+ ctx . deleteOriginal ( ) ;
146165 }
147166
148167 else if ( cardPlayed === "skip" ) {
@@ -154,6 +173,7 @@ You drew ${cardEmotes[newCards[0]]}`,
154173 game . currentCard = cardPlayed ;
155174 game . currentCardColor = color as typeof colors [ number ] ;
156175 game . cards [ ctx . member . id ] . splice ( game . cards [ ctx . member . id ] . indexOf ( cardPlayed ) , 1 ) ;
176+ delete game . saboteurs [ game . lastPlayer . id ] ;
157177
158178 if ( variant === "reverse" ) {
159179 game . players = game . players . reverse ( ) ;
0 commit comments