@@ -56,14 +56,20 @@ class Levels(commands.Cog):
5656 def __init__ (self , bot : SirRobin ):
5757 self .bot = bot
5858
59+ self .rules_folder_path = Path ("./bot/exts/levels/rules/" )
60+
5961 self .rules_all = []
6062 self .rules_pool = []
61- self .rules_active = []
62- self .rules_folder_path = Path ("./bot/exts/levels/rules/" )
63+ self .rules_active = [] # Active rules earn the points
64+ self .rule_anti_active = [] # Anti-active rules will halve the current points
65+
6366 self .active_rules_num = 3
67+ self .anti_active_rules_num = 1
6468
6569 self .active_reaction_rule_triggers = []
6670 self .active_message_rule_triggers = []
71+ self .anti_active_message_rule_triggers = []
72+ self .anti_active_reaction_rule_triggers = []
6773
6874
6975 async def cog_load (self ) -> None :
@@ -112,17 +118,19 @@ async def _load_rules(self) -> None:
112118 @tasks .loop (minutes = 42.0 )
113119 async def _cycle_rules_task (self ) -> None :
114120 """
115- Change which rules are currently active.
121+ Change which rules are currently active and anti-active .
116122
117123 Rules will statistically be used before a repeat is seen.
118124 This is not a guarnatee though.
119125 """
120- if len (self .rules_pool ) < self .active_rules_num :
126+ if len (self .rules_pool ) < ( self .active_rules_num + self . anti_active_rules_num ) :
121127 # If pool is empty, reshuffle completely to avoid activating same rule twice
122128 self .rules_pool = random .sample (self .rules_all , len (self .rules_all ))
123- self .rules_active = [self .rules_pool .pop () for _ in range (self .active_rules_num )]
124- logger .debug (f"Cycled active rules to: { [rule .name for rule in self .rules_active ]} " )
125129
130+ self .rules_active = [self .rules_pool .pop () for _ in range (self .active_rules_num )]
131+ self .rules_anti_active = [self .rules_pool .pop () for _ in range (self .anti_active_rules_num )]
132+ logger .info (f"Cycled active rules to: { [rule .name for rule in self .rules_active ]} " )
133+ logger .info (f"Cycled anti-active rule(s) to: { [rule .name for rule in self .rules_anti_active ]} " )
126134
127135 self .active_message_rule_triggers = [
128136 rule_trigger for rule in self .rules_active
@@ -132,6 +140,16 @@ async def _cycle_rules_task(self) -> None:
132140 rule_trigger for rule in self .rules_active
133141 for rule_trigger in rule .rule_triggers if rule_trigger .interaction_type == "reaction"
134142 ]
143+
144+ self .anti_active_message_rule_triggers = [
145+ rule_trigger for rule in self .rules_anti_active
146+ for rule_trigger in rule .rule_triggers if rule_trigger .interaction_type == "message"
147+ ]
148+ self .anti_active_reaction_rule_triggers = [
149+ rule_trigger for rule in self .rules_anti_active
150+ for rule_trigger in rule .rule_triggers if rule_trigger .interaction_type == "reaction"
151+ ]
152+
135153 self .all_message_rule_triggers = [
136154 rule_trigger for rule in self .rules_all
137155 for rule_trigger in rule .rule_triggers if rule_trigger .interaction_type == "message"
@@ -166,17 +184,20 @@ async def _calculate_point_thresholds_task(self) -> None:
166184 logger .debug (f"New thresholds: { thresholds } " )
167185
168186
169- async def _update_points (self , user_id : int , points : int ) -> None :
187+ async def _update_points (self , user_id : int , points : int , halve_points : bool = False ) -> None :
170188 """Updates user's score and ensures correct role is assigned."""
171- logger .debug (f"User { user_id } getting { points } points." )
189+ logger .debug (f"User { user_id } getting { points } points, halving override: { halve_points } ." )
172190 if not await self .user_points_cache .contains (user_id ):
173191 await self .user_points_cache .set (user_id , points )
174192 else :
175- if points == 0 :
193+ if points == 0 and not halve_points :
176194 return
177195
178196 current_points = await self .user_points_cache .get (user_id )
179197 new_point_total = current_points + points
198+ if halve_points :
199+ new_point_total = new_point_total // 2
200+
180201 await self .user_points_cache .set (user_id , new_point_total )
181202
182203 await self ._update_role_assignment (user_id )
@@ -218,6 +239,8 @@ async def on_message(self, msg: discord.Message) -> None:
218239 if len (self .active_message_rule_triggers ) == 0 :
219240 return
220241
242+ user_id = msg .author .id
243+
221244 total_points = 0
222245 rule_matches = 0
223246 for rule_trigger in self .active_message_rule_triggers :
@@ -227,12 +250,21 @@ async def on_message(self, msg: discord.Message) -> None:
227250 total_points += rule_trigger .points
228251 rule_matches += 1
229252
253+ anti_active_rule_matches = 0
254+ for anti_active_rule_trigger in self .anti_active_message_rule_triggers :
255+ re_pattern = anti_active_rule_trigger .message_content
256+ match = re .search (re_pattern , msg .content )
257+ if match :
258+ anti_active_rule_matches += 1
259+ rule_matches += 1
260+
261+ halving_points = anti_active_rule_matches > 0
262+
230263 # Only update points if they've matched any rules
231264 # If they match multiple rules and earn 0 points,
232265 # that should still get them a role
233266 if rule_matches != 0 :
234- user_id = msg .author .id
235- await self ._update_points (user_id , total_points )
267+ await self ._update_points (user_id , total_points , halve_points = halving_points )
236268
237269 total_rule_matches = 0
238270 for rule_trigger in self .all_message_rule_triggers :
@@ -270,11 +302,19 @@ async def on_reaction_add(self, reaction: discord.Reaction, user: discord.Member
270302 total_points += rule_trigger .points
271303 rule_matches += 1
272304
305+ anti_active_rule_matches = 0
306+ for anti_active_rule_trigger in self .anti_active_reaction_rule_triggers :
307+ if emoji_name in anti_active_rule_trigger .reaction_content :
308+ anti_active_rule_matches += 1
309+ rule_matches += 1
310+
311+ halving_points = anti_active_rule_matches > 0
312+
273313 # Only update points if they've matched any rules
274314 # If they match multiple rules and earn 0 points,
275315 # that should still get them a role
276316 if rule_matches != 0 :
277- await self ._update_points (user .id , total_points )
317+ await self ._update_points (user .id , total_points , halve_points = halving_points )
278318
279319
280320 @commands .group (name = "levels" )
0 commit comments