mirror of
https://github.com/solero/houdini.git
synced 2025-07-07 03:59:53 +00:00
fix innocent, golden card, and treasure book code redemption (#105)
* fix innocent, golden card, and treasure book code redemption innocent had a minor type error for some reason the code sent back with the confirmation packets for both golden and catalog does not force uppercase, causing the code key retrieval to fail this game sucks also fixed minor typo in getting player stamps * fix small typo in getting ninja rank forgot this one * fix golden card stamps and innocent also corrects elemental availability * add item support to treasure book codes just discovered "oneToOne" while poking around for other issues
This commit is contained in:
parent
95a7b25233
commit
94c410faca
@ -29,7 +29,7 @@ async def handle_get_ninja_ranks(p, penguin_id: int):
|
||||
ninja_rank, fire_ninja_rank, water_ninja_rank, snow_ninja_rank = await Penguin.select(
|
||||
'ninja_rank', 'fire_ninja_rank', 'water_ninja_rank', 'snow_ninja_rank'
|
||||
).where(Penguin.id == penguin_id).gino.first()
|
||||
await p.send_xt('gnr', p.id, ninja_rank, fire_ninja_rank, water_ninja_rank, snow_ninja_rank)
|
||||
await p.send_xt('gnr', penguin_id, ninja_rank, fire_ninja_rank, water_ninja_rank, snow_ninja_rank)
|
||||
|
||||
@handlers.handler(XTPacket('ni', 'gnl'))
|
||||
async def handle_get_ninja_level(p):
|
||||
|
@ -74,7 +74,7 @@ async def handle_get_player_stamps(p, player_id: int):
|
||||
stamps_string = p.server.cache.get(f'stamps.{player_id}')
|
||||
stamps_string = await get_player_stamps_string(p, player_id) if stamps_string is None else stamps_string
|
||||
p.server.cache.set(f'stamps.{player_id}', stamps_string)
|
||||
await p.send_xt('gps', p.id, stamps_string)
|
||||
await p.send_xt('gps', player_id, stamps_string)
|
||||
|
||||
|
||||
@handlers.handler(XTPacket('st', 'gmres'))
|
||||
|
@ -10,8 +10,7 @@ from houdini.data.redemption import PenguinRedemptionCode, RedemptionAwardCard,
|
||||
RedemptionAwardFlooring, RedemptionAwardFurniture, RedemptionAwardIgloo, RedemptionAwardItem, \
|
||||
RedemptionAwardLocation, RedemptionAwardPuffle, RedemptionAwardPuffleItem, RedemptionCode
|
||||
from houdini.handlers import XTPacket
|
||||
from houdini.handlers.games.ninja.card import ninja_rank_up
|
||||
from houdini.handlers.games.ninja.fire import fire_ninja_rank_up
|
||||
from houdini.penguin import Penguin
|
||||
|
||||
|
||||
TreasureUnlockCount = 3
|
||||
@ -20,6 +19,124 @@ FireNinjaRankUpChoice = 3
|
||||
WaterNinjaRankUpChoice = 4
|
||||
SnowNinjaRankUpChoice = 5
|
||||
|
||||
CardRewards = [4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 104, 6077, 4380, 2033, 1271]
|
||||
CardPostcards = {0: 177, 4: 178, 8: 179}
|
||||
CardStamps = {0: 230, 4: 232, 8: 234, 9: 236}
|
||||
|
||||
FireRewards = [6025, 4120, 2013, 1086, 3032]
|
||||
FireStamps = {1: 256, 3: 262}
|
||||
|
||||
WaterRewards = [6026, 4121, 2025, 1087, 3032]
|
||||
WaterStamps = {1: 278, 3: 282, 4: 284}
|
||||
|
||||
SnowRewards = {
|
||||
0: None,
|
||||
1: None, # Movie 1
|
||||
2: 6163, # Glacial Sandals
|
||||
3: None, # Movie 2
|
||||
4: None, # Movie 3
|
||||
5: 4834, # Coat of Frost
|
||||
6: None, # Movie 4
|
||||
7: None, # Movie 5
|
||||
8: 2119, # Icy Mask
|
||||
9: None, # Movie 6
|
||||
10: None, # Movie 7
|
||||
11: 1581, # Blizzard Helmet
|
||||
12: None, # Movie 8
|
||||
13: None, # Snow Gem - NOTE: awarded outside of the game server by a popup within Flash
|
||||
14: 1582, # Black Ice Headband
|
||||
15: 4835, # Frozen Armor
|
||||
16: 5223, # Ice Cap Cuffs
|
||||
17: 4836, # Black Ice Training Plates
|
||||
18: 1583, # The Flurry
|
||||
19: 6164, # Cold Snap Sandals
|
||||
20: 4837, # Snowstorm Gi
|
||||
21: 5224, # Storm Cloud Bracers,
|
||||
22: 5225, # Snow Shuriken
|
||||
23: 5226, # Fire Nunchaku
|
||||
24: 5227 # Water Hammer
|
||||
}
|
||||
|
||||
# Importing from houdini.handlers.games.ninja does not work due to room stamp groups
|
||||
async def ninja_rank_up(p: Penguin, ranks: int = 1) -> bool:
|
||||
"""
|
||||
Updates a Card-Jitsu rank for a penguin
|
||||
|
||||
Returns whether or not the player was able to rank up
|
||||
"""
|
||||
if p.ninja_rank + ranks > len(CardRewards):
|
||||
return False
|
||||
for rank in range(p.ninja_rank, p.ninja_rank + ranks):
|
||||
await p.add_inventory(
|
||||
p.server.items[CardRewards[rank]], cost=0, notify=False
|
||||
)
|
||||
if rank in CardStamps:
|
||||
await p.add_stamp(p.server.stamps[CardStamps[rank]])
|
||||
if rank in CardPostcards:
|
||||
await p.add_inbox(p.server.postcards[CardPostcards[rank]])
|
||||
|
||||
await p.update(ninja_rank=p.ninja_rank + ranks).apply()
|
||||
return True
|
||||
|
||||
async def fire_ninja_rank_up(p: Penguin, ranks: int = 1) -> bool:
|
||||
"""
|
||||
Updates a Card-Jitsu Fire rank for a penguin
|
||||
|
||||
Returns whether or not the player was able to rank up
|
||||
"""
|
||||
if p.fire_ninja_rank + ranks > len(FireRewards):
|
||||
return False
|
||||
for rank in range(p.fire_ninja_rank, p.fire_ninja_rank + ranks):
|
||||
await p.add_inventory(
|
||||
p.server.items[FireRewards[rank]], cost=0, notify=False
|
||||
)
|
||||
if rank in FireStamps:
|
||||
await p.add_stamp(p.server.stamps[FireStamps[rank]])
|
||||
|
||||
await p.update(fire_ninja_rank=p.fire_ninja_rank + ranks).apply()
|
||||
return True
|
||||
|
||||
async def water_ninja_rank_up(p: Penguin, ranks: int = 1) -> bool:
|
||||
"""
|
||||
Updates a Card-Jitsu Water rank for a penguin
|
||||
|
||||
Returns whether or not the player was able to rank up
|
||||
"""
|
||||
if p.water_ninja_rank + ranks > len(WaterRewards):
|
||||
return False
|
||||
for rank in range(p.water_ninja_rank, p.water_ninja_rank + ranks):
|
||||
await p.add_inventory(
|
||||
p.server.items[WaterRewards[rank]], cost=0, notify=False
|
||||
)
|
||||
if rank in WaterStamps:
|
||||
await p.add_stamp(p.server.stamps[WaterStamps[rank]])
|
||||
|
||||
await p.update(water_ninja_rank=p.water_ninja_rank + ranks).apply()
|
||||
return True
|
||||
|
||||
# Does not exist in Houdini
|
||||
async def snow_ninja_rank_up(p: Penguin, ranks: int = 1) -> bool:
|
||||
|
||||
"""
|
||||
Updates a Card-Jitsu Snow rank for a penguin
|
||||
|
||||
Returns whether or not the player was able to rank up
|
||||
"""
|
||||
if p.snow_ninja_rank + ranks >= 13:
|
||||
# Unlock "Snow Pro" stamp
|
||||
await p.add_stamp(p.server.stamps[487])
|
||||
if p.snow_ninja_rank + ranks > len(SnowRewards):
|
||||
return False
|
||||
for rank in range(p.snow_ninja_rank, p.snow_ninja_rank + ranks):
|
||||
if not (item := SnowRewards.get(rank)):
|
||||
continue
|
||||
await p.add_inventory(
|
||||
p.server.items[item], cost=0, notify=False
|
||||
)
|
||||
|
||||
await p.update(snow_ninja_rank=p.snow_ninja_rank + ranks).apply()
|
||||
return True
|
||||
|
||||
|
||||
@handlers.handler(XTPacket('rsc', ext='red'), pre_login=True, client=ClientType.Legacy)
|
||||
@handlers.depends_on_packet(XTPacket('rjs', ext='red'))
|
||||
@ -27,7 +144,7 @@ async def handle_code_legacy(p, redemption_code: str):
|
||||
query = RedemptionCode.distinct(RedemptionCode.id)\
|
||||
.load(cards=RedemptionAwardCard.distinct(RedemptionAwardCard.card_id),
|
||||
items=RedemptionAwardItem.distinct(RedemptionAwardItem.item_id))\
|
||||
.query.where(RedemptionCode.code == redemption_code)
|
||||
.query.where(RedemptionCode.code == redemption_code.upper())
|
||||
codes = await query.gino.all()
|
||||
if not codes:
|
||||
return await p.send_error(720)
|
||||
@ -64,7 +181,7 @@ async def handle_code_legacy(p, redemption_code: str):
|
||||
if code.items:
|
||||
for award in code.items:
|
||||
awards.append(str(award.item_id))
|
||||
await p.add_inventory(p.server.items[award.item_id], notify=False)
|
||||
await p.add_inventory(p.server.items[award.item_id], notify=False, cost=0)
|
||||
|
||||
await PenguinRedemptionCode.create(penguin_id=p.id, code_id=code.id)
|
||||
await p.update(coins=p.coins + code.coins).apply()
|
||||
@ -83,7 +200,7 @@ async def handle_code_vanilla(p, redemption_code: str):
|
||||
locations=RedemptionAwardLocation.distinct(RedemptionAwardLocation.location_id),
|
||||
puffles=RedemptionAwardPuffle.distinct(RedemptionAwardPuffle.puffle_id),
|
||||
puffle_items=RedemptionAwardPuffleItem.distinct(RedemptionAwardPuffleItem.puffle_item_id))\
|
||||
.query.where(RedemptionCode.code == redemption_code)
|
||||
.query.where(RedemptionCode.code == redemption_code.upper())
|
||||
codes = await query.gino.all()
|
||||
if not codes:
|
||||
return await p.send_error(720)
|
||||
@ -110,24 +227,87 @@ async def handle_code_vanilla(p, redemption_code: str):
|
||||
num_redeemed_codes = await PenguinRedemptionCode.join(RedemptionCode).count().where(
|
||||
(PenguinRedemptionCode.penguin_id == p.id) & (RedemptionCode.type == 'CATALOG')).gino.scalar()
|
||||
owned_ids = ','.join((str(item.id) for item in p.server.items.treasure if item.id in p.inventory))
|
||||
bad_items = 0
|
||||
|
||||
if code.items:
|
||||
for award in code.items:
|
||||
item_allowed = True
|
||||
if award.item_id in p.inventory:
|
||||
item_allowed = False
|
||||
bad_items += 1
|
||||
await p.add_inventory(p.server.items[award.item_id], notify=False, cost=0)
|
||||
awards.append(f'item{award.item_id},{int(item_allowed)}')
|
||||
if code.furniture:
|
||||
for award in code.furniture:
|
||||
item_allowed = True
|
||||
if award.furniture_id in p.furniture:
|
||||
penguin_furniture = p.furniture[award.furniture_id]
|
||||
if penguin_furniture.quantity >= p.server.furniture[award.furniture_id].max_quantity:
|
||||
item_allowed = False
|
||||
bad_items += 1
|
||||
await p.add_furniture(p.server.furniture[award.furniture_id], notify=False, cost=0)
|
||||
awards.append(f'f{award.furniture_id},{int(item_allowed)}')
|
||||
if code.igloos:
|
||||
for award in code.igloos:
|
||||
item_allowed = True
|
||||
if award.igloo_id in p.igloos:
|
||||
item_allowed = False
|
||||
bad_items += 1
|
||||
await p.add_igloo(p.server.igloos[award.igloo_id], notify=False, cost=0)
|
||||
awards.append(f'g{award.igloo_id},{int(item_allowed)}')
|
||||
if code.locations:
|
||||
for award in code.locations:
|
||||
item_allowed = True
|
||||
if award.location_id in p.locations:
|
||||
item_allowed = False
|
||||
bad_items += 1
|
||||
await p.add_location(p.server.locations[award.location_id], notify=False, cost=0)
|
||||
awards.append(f'loc{award.location_id},{int(item_allowed)}')
|
||||
if code.flooring:
|
||||
for award in code.flooring:
|
||||
item_allowed = True
|
||||
if award.flooring_id in p.flooring:
|
||||
item_allowed = False
|
||||
bad_items += 1
|
||||
await p.add_flooring(p.server.flooring[award.flooring_id], notify=False, cost=0)
|
||||
awards.append(f'flr{award.flooring_id},{int(item_allowed)}')
|
||||
if code.puffles:
|
||||
for award in code.puffles:
|
||||
item_allowed = True
|
||||
if len(p.puffles) >= 75:
|
||||
item_allowed = False
|
||||
bad_items += 1
|
||||
awards.append(f'p{award.puffle_id},{int(item_allowed)}')
|
||||
if code.puffle_items:
|
||||
for award in code.puffle_items:
|
||||
if award.puffle_item_id in p.puffle_items:
|
||||
penguin_care_item = p.puffle_items[award.puffle_item_id]
|
||||
if penguin_care_item.quantity >= 100:
|
||||
item_allowed = False
|
||||
bad_items += 1
|
||||
await p.add_puffle_item(p.server.puffle_items[award.puffle_item_id], notify=False, cost=0)
|
||||
awards.append(f'pi{award.puffle_item_id},{int(item_allowed)}')
|
||||
|
||||
p.allowed_redemption_items = TreasureUnlockCount + bad_items
|
||||
p.server.cache.set(f'{p.id}.{code.code}.treasure_code', code)
|
||||
return await p.send_xt('rsc', 'treasurebook', TreasureUnlockCount, owned_ids, num_redeemed_codes)
|
||||
return await p.send_xt('rsc', 'treasurebook', p.allowed_redemption_items, owned_ids, num_redeemed_codes, 0, int(len(awards) > 0), '|'.join(awards))
|
||||
|
||||
if code.type == 'GOLDEN':
|
||||
p.server.cache.set(f'{p.id}.{code.code}.golden_code', code)
|
||||
return await p.send_xt('rsc', 'GOLDEN', p.ninja_rank, p.fire_ninja_rank, p.water_ninja_rank, 0,
|
||||
int(p.fire_ninja_rank > 0), int(p.water_ninja_rank > 0), 0)
|
||||
return await p.send_xt('rsc', 'GOLDEN', p.ninja_rank, p.fire_ninja_rank, p.water_ninja_rank, p.snow_ninja_rank,
|
||||
1, 1, 1)
|
||||
|
||||
if code.type == 'INNOCENT':
|
||||
innocent_redeemed_items = {item for item in p.server.items.innocent if item.id in p.inventory}
|
||||
innocent_redeemed_furniture = {item for item in p.server.furniture.innocent if item.id in p.furniture}
|
||||
innocent_redeemed = innocent_redeemed_items.union(innocent_redeemed_furniture)
|
||||
innocent_items = set(p.server.items.innocent + p.server.furniture.innocent)
|
||||
innocent_clothing = {item for item in p.server.items.innocent}
|
||||
innocent_furniture = {item for item in p.server.furniture.innocent}
|
||||
innocent_items = innocent_clothing.union(innocent_furniture)
|
||||
|
||||
innocent_remaining = innocent_items - innocent_redeemed
|
||||
|
||||
choices = random.sample(innocent_remaining, min(len(innocent_remaining), 3))
|
||||
choices = random.sample(list(innocent_remaining), min(len(innocent_remaining), 3))
|
||||
if len(innocent_redeemed) + 3 == len(innocent_items):
|
||||
choices.append(p.server.igloos[53])
|
||||
for item in choices:
|
||||
@ -141,7 +321,7 @@ async def handle_code_vanilla(p, redemption_code: str):
|
||||
awards.append(f'f{item.id}')
|
||||
await p.add_furniture(item, notify=False, cost=0)
|
||||
|
||||
await PenguinRedemptionCode.create(penguin_id=p.id, code_id=code[0].id)
|
||||
await PenguinRedemptionCode.create(penguin_id=p.id, code_id=code.id)
|
||||
|
||||
return await p.send_xt('rsc', 'INNOCENT', ','.join(map(str, awards)),
|
||||
len(innocent_redeemed) + len(choices),
|
||||
@ -188,13 +368,14 @@ async def handle_code_vanilla(p, redemption_code: str):
|
||||
@handlers.handler(XTPacket('rsgc', ext='red'), pre_login=True)
|
||||
@handlers.depends_on_packet(XTPacket('rsc', ext='red'))
|
||||
async def handle_golden_choice(p, redemption_code: str, choice: int):
|
||||
code_key = f'{p.id}.{redemption_code}.golden_code'
|
||||
code_key = f'{p.id}.{redemption_code.upper()}.golden_code'
|
||||
code = p.server.cache.get(code_key)
|
||||
p.server.cache.delete(code_key)
|
||||
if not code:
|
||||
return await p.close()
|
||||
|
||||
if len(code.cards) < 6:
|
||||
p.logger.error("Golden card codes must have exactly 6 cards in redemption_award_card!")
|
||||
return await p.close()
|
||||
|
||||
cards = list(code.cards)
|
||||
@ -208,6 +389,14 @@ async def handle_golden_choice(p, redemption_code: str, choice: int):
|
||||
await fire_ninja_rank_up(p)
|
||||
cards = cards[:4]
|
||||
await p.send_xt('rsgc', ','.join(card_ids[:4]) + '|' + str(p.fire_ninja_rank))
|
||||
elif choice == WaterNinjaRankUpChoice:
|
||||
await water_ninja_rank_up(p)
|
||||
cards = cards[:4]
|
||||
await p.send_xt('rsgc', ','.join(card_ids[:4]) + '|' + str(p.water_ninja_rank))
|
||||
elif choice == SnowNinjaRankUpChoice:
|
||||
await snow_ninja_rank_up(p)
|
||||
cards = cards[:4]
|
||||
await p.send_xt('rsgc', ','.join(card_ids[:4]) + '|' + str(p.snow_ninja_rank))
|
||||
else:
|
||||
cards = cards[:4] + cards[-2:]
|
||||
await p.send_xt('rsgc', ','.join(card_ids[:4]) + '|' + ','.join(card_ids[-2:]))
|
||||
@ -221,7 +410,7 @@ async def handle_golden_choice(p, redemption_code: str, choice: int):
|
||||
@handlers.handler(XTPacket('rscrt', ext='red'), pre_login=True)
|
||||
@handlers.depends_on_packet(XTPacket('rsc', ext='red'))
|
||||
async def handle_send_cart(p, redemption_code: str, choice: str):
|
||||
code_key = f'{p.id}.{redemption_code}.treasure_code'
|
||||
code_key = f'{p.id}.{redemption_code.upper()}.treasure_code'
|
||||
code = p.server.cache.get(code_key)
|
||||
p.server.cache.delete(code_key)
|
||||
|
||||
@ -232,20 +421,21 @@ async def handle_send_cart(p, redemption_code: str, choice: str):
|
||||
awards = []
|
||||
choices = choice.split(',')
|
||||
|
||||
if len(choices) > TreasureUnlockCount:
|
||||
if len(choices) > p.allowed_redemption_items:
|
||||
return await p.close()
|
||||
|
||||
p.allowed_redemption_items = 0
|
||||
|
||||
for choice in choices:
|
||||
if choice.startswith('c'):
|
||||
coins += 500
|
||||
elif choice.startswith('p'):
|
||||
awards.append(choice)
|
||||
elif choice.isdigit():
|
||||
elif choice.isdigit() and p.server.items[int(choice)].treasure:
|
||||
awards.append(choice)
|
||||
await p.add_inventory(p.server.items[int(choice)], notify=False, cost=0)
|
||||
|
||||
if code.uses is not None:
|
||||
await PenguinRedemptionCode.create(penguin_id=p.id, code_id=code.id)
|
||||
await PenguinRedemptionCode.create(penguin_id=p.id, code_id=code.id)
|
||||
|
||||
await p.update(coins=p.coins + coins).apply()
|
||||
await p.send_xt('rscrt', ','.join(awards), coins or '')
|
||||
|
Loading…
x
Reference in New Issue
Block a user