rework shop
This commit is contained in:
@@ -181,18 +181,29 @@ async def use_consumable(
|
||||
# Get participant
|
||||
participant = await require_participant(db, current_user.id, data.marathon_id)
|
||||
|
||||
# For skip and reroll, we need the assignment
|
||||
# For some consumables, we need the assignment
|
||||
assignment = None
|
||||
if data.item_code in ["skip", "reroll"]:
|
||||
if data.item_code in ["skip", "wild_card", "copycat"]:
|
||||
if not data.assignment_id:
|
||||
raise HTTPException(status_code=400, detail="assignment_id is required for skip/reroll")
|
||||
raise HTTPException(status_code=400, detail=f"assignment_id is required for {data.item_code}")
|
||||
|
||||
result = await db.execute(
|
||||
select(Assignment).where(
|
||||
Assignment.id == data.assignment_id,
|
||||
Assignment.participant_id == participant.id,
|
||||
# For copycat, we need bonus_assignments to properly handle playthrough
|
||||
if data.item_code == "copycat":
|
||||
result = await db.execute(
|
||||
select(Assignment)
|
||||
.options(selectinload(Assignment.bonus_assignments))
|
||||
.where(
|
||||
Assignment.id == data.assignment_id,
|
||||
Assignment.participant_id == participant.id,
|
||||
)
|
||||
)
|
||||
else:
|
||||
result = await db.execute(
|
||||
select(Assignment).where(
|
||||
Assignment.id == data.assignment_id,
|
||||
Assignment.participant_id == participant.id,
|
||||
)
|
||||
)
|
||||
)
|
||||
assignment = result.scalar_one_or_none()
|
||||
if not assignment:
|
||||
raise HTTPException(status_code=404, detail="Assignment not found")
|
||||
@@ -201,15 +212,29 @@ async def use_consumable(
|
||||
if data.item_code == "skip":
|
||||
effect = await consumables_service.use_skip(db, current_user, participant, marathon, assignment)
|
||||
effect_description = "Assignment skipped without penalty"
|
||||
elif data.item_code == "shield":
|
||||
effect = await consumables_service.use_shield(db, current_user, participant, marathon)
|
||||
effect_description = "Shield activated - next drop will be free"
|
||||
elif data.item_code == "boost":
|
||||
effect = await consumables_service.use_boost(db, current_user, participant, marathon)
|
||||
effect_description = f"Boost x{effect['multiplier']} activated for next complete"
|
||||
elif data.item_code == "reroll":
|
||||
effect = await consumables_service.use_reroll(db, current_user, participant, marathon, assignment)
|
||||
effect_description = "Assignment rerolled - you can spin again"
|
||||
effect_description = f"Boost x{effect['multiplier']} activated for current assignment"
|
||||
elif data.item_code == "wild_card":
|
||||
if data.game_id is None:
|
||||
raise HTTPException(status_code=400, detail="game_id is required for wild_card")
|
||||
effect = await consumables_service.use_wild_card(
|
||||
db, current_user, participant, marathon, assignment, data.game_id
|
||||
)
|
||||
effect_description = f"New challenge from {effect['game_name']}: {effect['challenge_title']}"
|
||||
elif data.item_code == "lucky_dice":
|
||||
effect = await consumables_service.use_lucky_dice(db, current_user, participant, marathon)
|
||||
effect_description = f"Lucky Dice rolled: x{effect['multiplier']} multiplier"
|
||||
elif data.item_code == "copycat":
|
||||
if data.target_participant_id is None:
|
||||
raise HTTPException(status_code=400, detail="target_participant_id is required for copycat")
|
||||
effect = await consumables_service.use_copycat(
|
||||
db, current_user, participant, marathon, assignment, data.target_participant_id
|
||||
)
|
||||
effect_description = f"Copied challenge: {effect['challenge_title']}"
|
||||
elif data.item_code == "undo":
|
||||
effect = await consumables_service.use_undo(db, current_user, participant, marathon)
|
||||
effect_description = f"Restored {effect['points_restored']} points and streak {effect['streak_restored']}"
|
||||
else:
|
||||
raise HTTPException(status_code=400, detail=f"Unknown consumable: {data.item_code}")
|
||||
|
||||
@@ -243,9 +268,11 @@ async def get_consumables_status(
|
||||
|
||||
# Get inventory counts for all consumables
|
||||
skips_available = await consumables_service.get_consumable_count(db, current_user.id, "skip")
|
||||
shields_available = await consumables_service.get_consumable_count(db, current_user.id, "shield")
|
||||
boosts_available = await consumables_service.get_consumable_count(db, current_user.id, "boost")
|
||||
rerolls_available = await consumables_service.get_consumable_count(db, current_user.id, "reroll")
|
||||
wild_cards_available = await consumables_service.get_consumable_count(db, current_user.id, "wild_card")
|
||||
lucky_dice_available = await consumables_service.get_consumable_count(db, current_user.id, "lucky_dice")
|
||||
copycats_available = await consumables_service.get_consumable_count(db, current_user.id, "copycat")
|
||||
undos_available = await consumables_service.get_consumable_count(db, current_user.id, "undo")
|
||||
|
||||
# Calculate remaining skips for this marathon
|
||||
skips_remaining = None
|
||||
@@ -256,12 +283,16 @@ async def get_consumables_status(
|
||||
skips_available=skips_available,
|
||||
skips_used=participant.skips_used,
|
||||
skips_remaining=skips_remaining,
|
||||
shields_available=shields_available,
|
||||
has_shield=participant.has_shield,
|
||||
boosts_available=boosts_available,
|
||||
has_active_boost=participant.has_active_boost,
|
||||
boost_multiplier=consumables_service.BOOST_MULTIPLIER if participant.has_active_boost else None,
|
||||
rerolls_available=rerolls_available,
|
||||
wild_cards_available=wild_cards_available,
|
||||
lucky_dice_available=lucky_dice_available,
|
||||
has_lucky_dice=participant.has_lucky_dice,
|
||||
lucky_dice_multiplier=participant.lucky_dice_multiplier,
|
||||
copycats_available=copycats_available,
|
||||
undos_available=undos_available,
|
||||
can_undo=participant.can_undo,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -621,10 +621,12 @@ async def complete_assignment(
|
||||
if ba.status == BonusAssignmentStatus.COMPLETED.value:
|
||||
ba.points_earned = int(ba.challenge.points * multiplier)
|
||||
|
||||
# Apply boost multiplier from consumable
|
||||
# Apply boost and lucky dice multipliers from consumables
|
||||
boost_multiplier = consumables_service.consume_boost_on_complete(participant)
|
||||
if boost_multiplier > 1.0:
|
||||
total_points = int(total_points * boost_multiplier)
|
||||
lucky_dice_multiplier = consumables_service.consume_lucky_dice_on_complete(participant)
|
||||
combined_multiplier = boost_multiplier * lucky_dice_multiplier
|
||||
if combined_multiplier != 1.0:
|
||||
total_points = int(total_points * combined_multiplier)
|
||||
|
||||
# Update assignment
|
||||
assignment.status = AssignmentStatus.COMPLETED.value
|
||||
@@ -666,6 +668,8 @@ async def complete_assignment(
|
||||
activity_data["is_redo"] = True
|
||||
if boost_multiplier > 1.0:
|
||||
activity_data["boost_multiplier"] = boost_multiplier
|
||||
if lucky_dice_multiplier != 1.0:
|
||||
activity_data["lucky_dice_multiplier"] = lucky_dice_multiplier
|
||||
if coins_earned > 0:
|
||||
activity_data["coins_earned"] = coins_earned
|
||||
if playthrough_event:
|
||||
@@ -728,10 +732,12 @@ async def complete_assignment(
|
||||
total_points += common_enemy_bonus
|
||||
print(f"[COMMON_ENEMY] bonus={common_enemy_bonus}, closed={common_enemy_closed}, winners={common_enemy_winners}")
|
||||
|
||||
# Apply boost multiplier from consumable
|
||||
# Apply boost and lucky dice multipliers from consumables
|
||||
boost_multiplier = consumables_service.consume_boost_on_complete(participant)
|
||||
if boost_multiplier > 1.0:
|
||||
total_points = int(total_points * boost_multiplier)
|
||||
lucky_dice_multiplier = consumables_service.consume_lucky_dice_on_complete(participant)
|
||||
combined_multiplier = boost_multiplier * lucky_dice_multiplier
|
||||
if combined_multiplier != 1.0:
|
||||
total_points = int(total_points * combined_multiplier)
|
||||
|
||||
# Update assignment
|
||||
assignment.status = AssignmentStatus.COMPLETED.value
|
||||
@@ -772,6 +778,8 @@ async def complete_assignment(
|
||||
activity_data["is_redo"] = True
|
||||
if boost_multiplier > 1.0:
|
||||
activity_data["boost_multiplier"] = boost_multiplier
|
||||
if lucky_dice_multiplier != 1.0:
|
||||
activity_data["lucky_dice_multiplier"] = lucky_dice_multiplier
|
||||
if coins_earned > 0:
|
||||
activity_data["coins_earned"] = coins_earned
|
||||
if assignment.event_type == EventType.JACKPOT.value:
|
||||
@@ -887,11 +895,10 @@ async def drop_assignment(assignment_id: int, current_user: CurrentUser, db: DbS
|
||||
participant.drop_count, game.playthrough_points, playthrough_event
|
||||
)
|
||||
|
||||
# Check for shield - if active, no penalty
|
||||
shield_used = False
|
||||
if consumables_service.consume_shield(participant):
|
||||
penalty = 0
|
||||
shield_used = True
|
||||
# Save drop data for potential undo
|
||||
consumables_service.save_drop_for_undo(
|
||||
participant, penalty, participant.current_streak
|
||||
)
|
||||
|
||||
# Update assignment
|
||||
assignment.status = AssignmentStatus.DROPPED.value
|
||||
@@ -921,8 +928,6 @@ async def drop_assignment(assignment_id: int, current_user: CurrentUser, db: DbS
|
||||
"penalty": penalty,
|
||||
"lost_bonuses": completed_bonuses_count,
|
||||
}
|
||||
if shield_used:
|
||||
activity_data["shield_used"] = True
|
||||
if playthrough_event:
|
||||
activity_data["event_type"] = playthrough_event.type
|
||||
activity_data["free_drop"] = True
|
||||
@@ -941,7 +946,6 @@ async def drop_assignment(assignment_id: int, current_user: CurrentUser, db: DbS
|
||||
penalty=penalty,
|
||||
total_points=participant.total_points,
|
||||
new_drop_count=participant.drop_count,
|
||||
shield_used=shield_used,
|
||||
)
|
||||
|
||||
# Regular challenge drop
|
||||
@@ -953,11 +957,10 @@ async def drop_assignment(assignment_id: int, current_user: CurrentUser, db: DbS
|
||||
# Calculate penalty (0 if double_risk event is active)
|
||||
penalty = points_service.calculate_drop_penalty(participant.drop_count, assignment.challenge.points, active_event)
|
||||
|
||||
# Check for shield - if active, no penalty
|
||||
shield_used = False
|
||||
if consumables_service.consume_shield(participant):
|
||||
penalty = 0
|
||||
shield_used = True
|
||||
# Save drop data for potential undo
|
||||
consumables_service.save_drop_for_undo(
|
||||
participant, penalty, participant.current_streak
|
||||
)
|
||||
|
||||
# Update assignment
|
||||
assignment.status = AssignmentStatus.DROPPED.value
|
||||
@@ -975,8 +978,6 @@ async def drop_assignment(assignment_id: int, current_user: CurrentUser, db: DbS
|
||||
"difficulty": assignment.challenge.difficulty,
|
||||
"penalty": penalty,
|
||||
}
|
||||
if shield_used:
|
||||
activity_data["shield_used"] = True
|
||||
if active_event:
|
||||
activity_data["event_type"] = active_event.type
|
||||
if active_event.type == EventType.DOUBLE_RISK.value:
|
||||
@@ -996,7 +997,6 @@ async def drop_assignment(assignment_id: int, current_user: CurrentUser, db: DbS
|
||||
penalty=penalty,
|
||||
total_points=participant.total_points,
|
||||
new_drop_count=participant.drop_count,
|
||||
shield_used=shield_used,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user