diff --git a/src/packing/player.cairo b/src/packing/player.cairo index b8c57934..a5c6743b 100644 --- a/src/packing/player.cairo +++ b/src/packing/player.cairo @@ -191,7 +191,7 @@ impl PlayerImpl of PlayerTrait { } // update drug level - self.drug_level = drug_level; + game_store.player.drug_level = drug_level; // randomize price for new drug game_store.markets.shuffle_drug_prices(ref randomizer, drug_level.into()); diff --git a/src/packing/wanted_packed.cairo b/src/packing/wanted_packed.cairo index e8841bdd..654c3cb8 100644 --- a/src/packing/wanted_packed.cairo +++ b/src/packing/wanted_packed.cairo @@ -73,30 +73,24 @@ impl WantedPackedImpl of WantedPackedTrait { fn on_turn_end(ref self: WantedPacked, game_store: GameStore) { let mut locations = LocationsEnumerableImpl::all(); + let drugs = game_store.drugs.get(); loop { match locations.pop_front() { Option::Some(location) => { let mut value = self.get(*location); - if game_store.player.next_location == *location { - if game_store.player.next_location == game_store.player.prev_location { - // travel back to same location : +3 - self.set(*location, value.add_capped(3, 7)); - } else { - let drugs = game_store.drugs.get(); - if drugs.quantity > 0 { - // travel to location with drugs : +2 - self.set(*location, value.add_capped(2, 7)); - }; - } - } else { - //not current location / not prev_location - if game_store.player.location != *location - && game_store.player.prev_location != *location { - // nothin at location : -1 - self.set(*location, value.sub_capped(1, 0)); - } + if game_store.player.next_location == *location && game_store.player.next_location == game_store.player.prev_location { + // travel back to same location : +3 + self.set(*location, value.add_capped(3, 7)); + } else if game_store.player.location == *location { + // leaving current location with drugs : +4 + if drugs.quantity > 0 { + self.set(*location, value.add_capped(4, 7)); + }; + } else if *location != game_store.player.next_location { + // not next / not prev / not current : -1 + self.set(*location, value.sub_capped(1, 0)); } }, Option::None => { break; } diff --git a/src/systems/game.cairo b/src/systems/game.cairo index 9f839d7a..7048ad16 100644 --- a/src/systems/game.cairo +++ b/src/systems/game.cairo @@ -27,6 +27,7 @@ trait IGameActions { fn claim(self: @T, season: u16); } + #[dojo::contract] mod game { use starknet::{ContractAddress, get_caller_address, get_contract_address}; @@ -145,13 +146,14 @@ mod game { action: EncounterActions, outcome: EncounterOutcomes, rounds: u8, - dmg_dealt: u8, - dmg_taken: u8, + dmg_dealt: Array<(u8,u8)>, + dmg_taken: Array<(u8,u8)>, cash_earnt: u32, cash_loss: u32, drug_id: u8, - drug_loss: u32, + drug_loss: Array, turn_loss: u8, + escaped_with_item: bool, } #[derive(Drop, Serde, starknet::Event)] diff --git a/src/systems/traveling.cairo b/src/systems/traveling.cairo index e4ddb90f..a187b4ab 100644 --- a/src/systems/traveling.cairo +++ b/src/systems/traveling.cairo @@ -1,25 +1,21 @@ -use rollyourown::packing::drugs_packed::DrugsPackedTrait; -use rollyourown::utils::random::RandomTrait; use core::traits::TryInto; -use rollyourown::packing::items_packed::ItemsPackedTrait; -use rollyourown::packing::encounters_packed::EncountersPackedTrait; use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; use rollyourown::{ models::game::{Game}, utils::{ - random::{Random, RandomImpl}, math::{MathTrait, MathImplU8}, + random::{Random, RandomImpl, RandomTrait}, math::{MathTrait, MathImplU8}, events::{RawEventEmitterTrait, RawEventEmitterImpl} }, config::{ - hustlers::{HustlerItemConfig, ItemSlot}, locations::{Locations, LocationsRandomizableImpl} + hustlers::{HustlerItemConfig,HustlerItemTiersConfig, ItemSlot}, locations::{Locations, LocationsRandomizableImpl} }, packing::{ game_store::{GameStore}, player::{PlayerImpl, PlayerStatus}, - wanted_packed::{WantedPacked, WantedPackedImpl}, items_packed::{ItemsPackedImpl}, - encounters_packed::{Encounters, EncountersPackedImpl}, - drugs_packed::{DrugsPacked, DrugsPackedImpl, DrugsUnpacked} + wanted_packed::{WantedPacked, WantedPackedImpl}, items_packed::{ItemsPackedImpl, ItemsPackedTrait}, + encounters_packed::{Encounters, EncountersPackedImpl, EncountersPackedTrait}, + drugs_packed::{DrugsPacked, DrugsPackedImpl, DrugsUnpacked, DrugsPackedTrait} }, - systems::game::{EncounterActions, game::TravelEncounterResult} + systems::game::{EncounterActions, game::TravelEncounterResult, game::Event} }; #[derive(Copy, Drop, Serde, PartialEq)] @@ -145,8 +141,6 @@ fn get_encounter_by_slot(game_store: GameStore, encounter_slot: Encounters) -> E } } -// fn get_encounter(ref self: EncountersPacked, ref randomizer: Random) -> Encounter { - fn on_travel(ref game_store: GameStore, ref randomizer: Random) -> (bool, bool) { // get wanted level at destination 0-7 let wanted_risk = game_store.wanted.get_wanted_risk(game_store.player.next_location); @@ -236,28 +230,47 @@ fn decide(ref game_store: GameStore, ref randomizer: Random, action: EncounterAc EncounterActions::Fight => { on_fight(ref game_store, ref randomizer, encounter) }, }; - // emit event - game_store - .world - .emit_raw( - array![ - selector!("TravelEncounterResult"), - Into::::into(game_store.game.game_id), - Into::::into(game_store.game.player_id).into() - ], - array![ - Into::::into(result.action).into(), - Into::::into(result.outcome).into(), - Into::::into(result.rounds), - Into::::into(result.dmg_dealt), - Into::::into(result.dmg_taken), - Into::::into(result.cash_earnt), - Into::::into(result.cash_loss), - Into::::into(result.drug_id), - Into::::into(result.drug_loss), - Into::::into(result.turn_loss), - ], - ); + + let result_event = TravelEncounterResult { + game_id: game_store.game.game_id, + player_id: game_store.game.player_id, + action: result.action, + outcome: result.outcome, + rounds: result.rounds, + dmg_dealt: result.dmg_dealt, + dmg_taken: result.dmg_taken, + cash_earnt: result.cash_earnt, + cash_loss: result.cash_loss, + drug_id: result.drug_id, + drug_loss: result.drug_loss, + turn_loss: result.turn_loss, + escaped_with_item: result.escaped_with_item, + }; + + emit!( game_store.world, result_event); + + // // emit event + // game_store + // .world + // .emit_raw( + // array![ + // selector!("TravelEncounterResult"), + // Into::::into(game_store.game.game_id), + // Into::::into(game_store.game.player_id).into() + // ], + // array![ + // Into::::into(result.action).into(), + // Into::::into(result.outcome).into(), + // Into::::into(result.rounds), + // Into::::into(result.dmg_dealt), + // Into::::into(result.dmg_taken), + // Into::::into(result.cash_earnt), + // Into::::into(result.cash_loss), + // Into::::into(result.drug_id), + // Into::::into(result.drug_loss), + // Into::::into(result.turn_loss), + // ], + // ); let is_dead = game_store.player.is_dead(); if !is_dead { @@ -275,17 +288,18 @@ fn on_pay( ref game_store: GameStore, ref randomizer: Random, encounter: Encounter ) -> TravelEncounterResult { let mut drug_id: u8 = 0; - let mut drug_loss: u32 = 0; + let mut drug_loss: Array = array![]; let mut cash_loss: u32 = 0; - let mut dmg_taken: u8 = 0; + let mut dmg_taken: Array<(u8,u8)> = array![]; match encounter.encounter { Encounters::Cops => { // pay demand_pct drugs let mut drug_unpacked = game_store.drugs.get(); - drug_loss = drug_unpacked.quantity.pct(encounter.demand_pct.into()); + let quantity_lost = drug_unpacked.quantity.pct(encounter.demand_pct.into()); drug_id = drug_unpacked.drug.into(); - drug_unpacked.quantity -= drug_loss; + drug_loss.append(quantity_lost); + drug_unpacked.quantity -= quantity_lost; // set drugs game_store.drugs.set(drug_unpacked); @@ -293,13 +307,16 @@ fn on_pay( Encounters::Gang => { // calc cash_loss cash_loss = game_store.player.cash.pct(encounter.demand_pct.into()); + // gang make u lose 1 extra hp (but can't die) - dmg_taken = 1; + if game_store.player.health > 1 { + // update player health + game_store.player.health -= 1; + dmg_taken.append((1,0)); + } // update player cash game_store.player.cash -= cash_loss; - // update player health - game_store.player.health = game_store.player.health.sub_capped(dmg_taken, 1); }, }; @@ -309,13 +326,14 @@ fn on_pay( action: EncounterActions::Pay, outcome: EncounterOutcomes::Paid, rounds: 0, - dmg_dealt: 0, + dmg_dealt: array![], dmg_taken, cash_earnt: 0, cash_loss, drug_id, drug_loss, - turn_loss: 0 + turn_loss: 0, + escaped_with_item: false, } } @@ -323,7 +341,7 @@ fn on_pay( fn on_run( ref game_store: GameStore, ref randomizer: Random, encounter: Encounter ) -> TravelEncounterResult { - // TODO: adjust with items + // TODO: make configurable let initial_capture_rate: u8 = 82; // 82% chance of capture let player_defense: u8 = game_store @@ -333,6 +351,7 @@ fn on_run( .stat .try_into() .unwrap(); + let player_speed: u8 = game_store.items.get_item(ItemSlot::Feet).tier.stat.try_into().unwrap(); let capture_rate = initial_capture_rate.sub_capped(player_speed, 0); @@ -341,27 +360,34 @@ fn on_run( let drug_id: u8 = drug_unpacked.drug.into(); let mut rounds = 0; - let mut dmg_taken = 0; - let mut drug_loss = 0; + let mut dmg_taken = array![]; + let mut drug_loss: Array = array![]; let mut turn_loss = 0; let mut is_dead = false; let mut is_caught = false; + let mut escaped_with_item = false; + + let initial_tier_defense: u8 = (get!(game_store.world, (ItemSlot::Clothes, 1), (HustlerItemTiersConfig)).stat / 10).try_into().unwrap(); + let def = player_defense / 10; // loop until resolution loop { rounds += 1; - let is_captured = randomizer.occurs(capture_rate); + + let rand_0_99 = randomizer.between::(0,100); + let is_captured = rand_0_99 < capture_rate; if is_captured { //encounter___attack = encounter_level * 2 + turn / 3; // reduce attack with defense - let def = player_defense / 10; let health_loss = encounter.attack.sub_capped(def, 1); + let health_saved = def - initial_tier_defense; // take dmgs game_store.player.health = game_store.player.health.sub_capped(health_loss, 0); - dmg_taken += health_loss; + //dmg_taken += health_loss; + dmg_taken.append((health_loss, health_saved)); // loss a 2 or 1% drug each round xd let loss_pct = drug_unpacked.quantity.pct(1); @@ -370,7 +396,7 @@ fn on_run( } else { loss_pct }; - drug_loss += loss; + drug_loss.append(loss); drug_unpacked.quantity = drug_unpacked.quantity.sub_capped(loss, 0); // set drugs @@ -383,6 +409,7 @@ fn on_run( break; } } else { + escaped_with_item = rand_0_99 <= player_speed; break; }; @@ -433,13 +460,14 @@ fn on_run( action: EncounterActions::Run, outcome, rounds, - dmg_dealt: 0, + dmg_dealt: array![], dmg_taken, cash_earnt: 0, cash_loss: 0, drug_id, drug_loss, turn_loss, + escaped_with_item, } } @@ -453,6 +481,7 @@ fn on_fight( .stat .try_into() .unwrap(); + let player_defense: u8 = game_store .items .get_item(ItemSlot::Clothes) @@ -460,14 +489,18 @@ fn on_fight( .stat .try_into() .unwrap(); + + let initial_tier_attack: u8 = (get!(game_store.world, (ItemSlot::Weapon, 1), (HustlerItemTiersConfig)).stat / 2).try_into().unwrap(); + let initial_tier_defense: u8 = (get!(game_store.world, (ItemSlot::Clothes, 1), (HustlerItemTiersConfig)).stat / 10).try_into().unwrap(); + let atk = player_attack / 2; let def = player_defense / 10; let mut rounds = 0; - let mut dmg_taken = 0; - let mut dmg_dealt = 0; + let mut dmg_taken: Array<(u8,u8)> = array![]; + let mut dmg_dealt: Array<(u8,u8)> = array![]; let mut is_dead = false; - + let mut encounter = encounter; // loop until resolution @@ -476,7 +509,7 @@ fn on_fight( // player attack encounter.health = encounter.health.sub_capped(atk, 0); - dmg_dealt += atk; + dmg_dealt.append((atk, atk - initial_tier_attack)); // check if encounter is dead if encounter.health == 0 { @@ -486,7 +519,7 @@ fn on_fight( // encounter attack let encounter_atk = encounter.attack.sub_capped(def, 1); game_store.player.health = game_store.player.health.sub_capped(encounter_atk, 0); - dmg_taken += encounter_atk; + dmg_taken.append((encounter_atk, def - initial_tier_defense)); // check if player is dead if game_store.player.health == 0 { @@ -521,8 +554,9 @@ fn on_fight( cash_earnt, cash_loss: 0, drug_id: 0, - drug_loss: 0, + drug_loss: array![], turn_loss: 0, + escaped_with_item: false, } } diff --git a/web/manifest.json b/web/manifest.json index b0733f56..95f40e49 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -1551,7 +1551,7 @@ { "name": "rollyourown::config::config::config", "address": "0x73e5a7b0f2ff860ae67f9edc7709d3dbbee30f84afcccf1f8e3963e128e1bc5", - "class_hash": "0x3121813bc42833edb9e219367b4e33c04bcd8242ad1fffb372ff5463288a80e", + "class_hash": "0x6b4878e20f74c38e424c4dc69013c18a1a02847e4b2a66e090e32b2754f0423", "abi": [ { "type": "impl", @@ -2024,7 +2024,7 @@ { "name": "rollyourown::systems::game::game", "address": "0x52d79bdb709ee84fbf0199f427d058977a04c5403f149796ad9d76927a162ec", - "class_hash": "0x669b993b322f4fed45b98dd5f528d9878b9acf0801fc0aa4365a07d68521033", + "class_hash": "0x24af60a57ee7129362cec3b106c4ac98bb1bb66f5dff04164f50d96f9dac9af", "abi": [ { "type": "impl", @@ -2697,12 +2697,12 @@ }, { "name": "dmg_dealt", - "type": "core::integer::u8", + "type": "core::array::Array::<(core::integer::u8, core::integer::u8)>", "kind": "data" }, { "name": "dmg_taken", - "type": "core::integer::u8", + "type": "core::array::Array::<(core::integer::u8, core::integer::u8)>", "kind": "data" }, { @@ -2722,13 +2722,18 @@ }, { "name": "drug_loss", - "type": "core::integer::u32", + "type": "core::array::Array::", "kind": "data" }, { "name": "turn_loss", "type": "core::integer::u8", "kind": "data" + }, + { + "name": "escaped_with_item", + "type": "core::bool", + "kind": "data" } ] }, diff --git a/web/src/dojo/class/Events.ts b/web/src/dojo/class/Events.ts index 53886ca3..83653a9f 100644 --- a/web/src/dojo/class/Events.ts +++ b/web/src/dojo/class/Events.ts @@ -30,7 +30,9 @@ export class EventClass { makeObservable(this, { events: observable, playerName: computed, - sortedEvents: computed + sortedEvents: computed, + lastEncounter: computed, + lastEncounterResult: computed, }) console.log("Events", this) @@ -75,13 +77,13 @@ export class EventClass { } - getLastEncounter() { + get lastEncounter() { return this .sortedEvents .findLast((i: DojoEvent) => (i.parsed as BaseEventData).eventType === WorldEvents.TravelEncounter) } - getLastEncounterResult() { + get lastEncounterResult() { return this .sortedEvents .findLast((i: DojoEvent) => (i.parsed as BaseEventData).eventType === WorldEvents.TravelEncounterResult) diff --git a/web/src/dojo/events.ts b/web/src/dojo/events.ts index 8e17dfb8..3440c77d 100644 --- a/web/src/dojo/events.ts +++ b/web/src/dojo/events.ts @@ -7,6 +7,14 @@ import { import { WorldEvents } from "./generated/contractEvents"; +import { Contract } from "starknet"; + +import manifest from "../../manifest.json"; + +const contract = manifest.contracts.find(i => i.name === "rollyourown::systems::game::game")! +const gameContract = new Contract(contract.abi, contract.address) + + export interface BaseEventData { gameId: string; eventType: WorldEvents; @@ -65,13 +73,14 @@ export interface TravelEncounterResultData extends BaseEventData { action: EncountersAction; outcome: EncounterOutcomes; rounds: number; - dmgDealt: number; - dmgTaken: number; + dmgDealt: Array<{ 0: number, 1: number }>; + dmgTaken: Array<{ 0: number, 1: number }>; cashEarnt: number; cashLoss: number; drugId: number; - drugLoss: number; + drugLoss: Array; turnLoss: number; + escapedWithItem: boolean; } @@ -193,6 +202,18 @@ export const parseEvent = (raw: any) => { case WorldEvents.TravelEncounterResult: + // use gameContract to parseEvents (Array<(u8,u8)>...) + + //@ts-ignore + const parsedEvents = gameContract.parseEvents({ + events: [{ + from_address: gameContract.address, + keys: [...raw.keys], // parseEvents consumes keys with iterators? + data: [...raw.data], // parseEvents consumes data with iterators? + }] + }) + const parsed = parsedEvents[0]!["TravelEncounterResult"]!; + return { eventType: WorldEvents.TravelEncounterResult, eventName: "TravelEncounterResult", @@ -201,13 +222,18 @@ export const parseEvent = (raw: any) => { action: Number(raw.data[0]) as EncountersAction, outcome: Number(raw.data[1]) as EncounterOutcomes, rounds: Number(raw.data[2]), - dmgDealt: Number(raw.data[3]), - dmgTaken: Number(raw.data[4]), - cashEarnt: Number(raw.data[5]), - cashLoss: Number(raw.data[6]), - drugId: Number(raw.data[7]), - drugLoss: Number(raw.data[8]), - turnLoss: Number(raw.data[9]), + // + //@ts-ignore + dmgDealt: parsed.dmg_dealt.map(i => ({ "0": Number(i[0]), "1": Number(i[1]) })), + //@ts-ignore + dmgTaken: parsed.dmg_taken.map(i => ({ "0": Number(i[0]), "1": Number(i[1]) })), + cashEarnt: Number(parsed.cash_earnt), + cashLoss: Number(parsed.cash_loss), + drugId: Number(parsed.drug_id), + //@ts-ignore + drugLoss: parsed.drug_loss.map(i => Number(i)), + turnLoss: Number(parsed.turn_loss), + escapedWithItem: parsed.escapedWithItem as unknown as boolean, } as TravelEncounterResultData; diff --git a/web/src/dojo/generated/contractEvents.ts b/web/src/dojo/generated/contractEvents.ts index 906e95bc..4087ae5d 100644 --- a/web/src/dojo/generated/contractEvents.ts +++ b/web/src/dojo/generated/contractEvents.ts @@ -94,13 +94,14 @@ player_id: string; action: String; outcome: String; rounds: number; -dmg_dealt: number; -dmg_taken: number; +dmg_dealt: String; +dmg_taken: String; cash_earnt: number; cash_loss: number; drug_id: number; -drug_loss: number; +drug_loss: String; turn_loss: number; +escaped_with_item: boolean; } export interface MeetOGData extends BaseEventData { @@ -238,13 +239,14 @@ player_id: num.toHexString(raw.keys[2]), action: num.toHexString(raw.data[0]), outcome: num.toHexString(raw.data[1]), rounds: Number(raw.data[2]), -dmg_dealt: Number(raw.data[3]), -dmg_taken: Number(raw.data[4]), +dmg_dealt: num.toHexString(raw.data[3]), +dmg_taken: num.toHexString(raw.data[4]), cash_earnt: Number(raw.data[5]), cash_loss: Number(raw.data[6]), drug_id: Number(raw.data[7]), -drug_loss: Number(raw.data[8]), +drug_loss: num.toHexString(raw.data[8]), turn_loss: Number(raw.data[9]), +escaped_with_item: raw.data[10] === "0x0" ? false : true, } as TravelEncounterResultData; case WorldEvents.MeetOG: diff --git a/web/src/dojo/hooks/useSystems.ts b/web/src/dojo/hooks/useSystems.ts index 89e347b0..d61428cf 100644 --- a/web/src/dojo/hooks/useSystems.ts +++ b/web/src/dojo/hooks/useSystems.ts @@ -3,8 +3,9 @@ import { getEvents } from "@dojoengine/utils"; import { useAccount } from "@starknet-react/core"; import { useCallback, useState } from "react"; import { - BigNumberish, Call, GetTransactionReceiptResponse, - shortString, uint256 + BigNumberish, Call, + GetTransactionReceiptResponse, + shortString, uint256 } from "starknet"; import { PendingCall, pendingCallToCairoEnum } from "../class/Game"; import { BaseEventData, GameCreatedData, HighVolatilityData, TravelEncounterData, TravelEncounterResultData, parseAllEvents } from "../events"; @@ -42,13 +43,11 @@ export type DojoCall = { } - const sleep = (ms: number) => { return new Promise(resolve => setTimeout(resolve, ms)); } const tryBetterErrorMsg = (msg: string): string => { - const failureReasonIndex = msg.indexOf("Failure reason") if (failureReasonIndex > 0) { let betterMsg = msg.substring(failureReasonIndex) @@ -58,17 +57,16 @@ const tryBetterErrorMsg = (msg: string): string => { } return msg; - } export const useSystems = (): SystemsInterface => { const { //account, dojoProvider, - configStore + configStore, + } = useDojoContext(); const { account } = useAccount() - const { config } = useConfigStore(); const { toast, clear: clearToasts } = useToast(); @@ -76,6 +74,7 @@ export const useSystems = (): SystemsInterface => { const [isPending, setIsPending] = useState(false); const [error, setError] = useState(undefined); + const executeAndReceipt = useCallback( async (params: DojoCall | Call[]): Promise<{ hash: string; diff --git a/web/src/pages/[gameId]/[locationSlug]/index.tsx b/web/src/pages/[gameId]/[locationSlug]/index.tsx index e773f56f..3cdf5ea2 100644 --- a/web/src/pages/[gameId]/[locationSlug]/index.tsx +++ b/web/src/pages/[gameId]/[locationSlug]/index.tsx @@ -56,7 +56,6 @@ const Location = observer(() => { } }, [location, game]); - console.log(game) if (!game || !gameInfos || !prices || !location || !configStore || !gameId) { return <>; } diff --git a/web/src/pages/[gameId]/event/consequence.tsx b/web/src/pages/[gameId]/event/consequence.tsx index 39600eb8..f0551b7d 100644 --- a/web/src/pages/[gameId]/event/consequence.tsx +++ b/web/src/pages/[gameId]/event/consequence.tsx @@ -1,17 +1,20 @@ import { Button } from "@/components/common"; +import { Heart } from "@/components/icons"; import { Footer, Layout } from "@/components/layout"; import { TravelEncounterData, TravelEncounterResultData } from "@/dojo/events"; import { getOutcomeInfo } from "@/dojo/helpers"; -import { useConfigStore, useDojoContext, useGameStore, useRouterContext } from "@/dojo/hooks"; -import { EncounterOutcomes, Encounters, OutcomeInfo } from "@/dojo/types"; +import { useConfigStore, useGameStore, useRouterContext } from "@/dojo/hooks"; +import { EncounterOutcomes, Encounters, EncountersAction, OutcomeInfo } from "@/dojo/types"; import { Sounds, playSound } from "@/hooks/sound"; import { formatCash } from "@/utils/ui"; -import { Box, Heading, Image, Text, VStack } from "@chakra-ui/react"; -import { useEffect, useState } from "react"; +import { Box, Card, HStack, Heading, Image, Text, VStack } from "@chakra-ui/react"; +import { useAccount } from "@starknet-react/core"; +import { observer } from "mobx-react-lite"; +import { ReactNode, useEffect, useState } from "react"; -export default function Consequence() { +const Consequence = () => { const { router, gameId } = useRouterContext(); - const { account } = useDojoContext(); + const { account } = useAccount(); const configStore = useConfigStore(); const { game, gameEvents } = useGameStore(); @@ -22,18 +25,17 @@ export default function Consequence() { //const response = useMemo(() => outcome?.getResponse(true), [outcome]); useEffect(() => { - if (!(game && gameEvents)) return; + if (!(game && gameEvents && gameEvents?.events && gameEvents?.lastEncounter && gameEvents?.lastEncounterResult)) + return; - const lastEncounter = gameEvents.getLastEncounter(); - const lastEncounterResult = gameEvents.getLastEncounterResult(); - lastEncounterResult && setEncounterResult(lastEncounterResult.parsed as TravelEncounterResultData); + setEncounterResult(gameEvents?.lastEncounterResult.parsed as TravelEncounterResultData); const outcome = getOutcomeInfo( - (lastEncounter?.parsed as TravelEncounterData).encounterId as Encounters, - (lastEncounterResult?.parsed as TravelEncounterResultData).outcome as EncounterOutcomes, + (gameEvents?.lastEncounter.parsed as TravelEncounterData).encounterId as Encounters, + (gameEvents?.lastEncounterResult?.parsed as TravelEncounterResultData).outcome as EncounterOutcomes, ); setOutcomeInfos(outcome); - }, [game, gameEvents, gameEvents?.events]); + }, [game, gameEvents, gameEvents?.sortedEvents, gameEvents?.lastEncounter, gameEvents?.lastEncounterResult]); useEffect(() => { if (encounterResult && encounterResult.outcome === EncounterOutcomes.Died) { @@ -76,7 +78,7 @@ export default function Consequence() { } > - + {outcomeInfos.title} @@ -85,35 +87,109 @@ export default function Consequence() { {outcomeInfos.name} - {outcomeInfos.name} - - - {/* {response}*/} - {encounterResult.rounds > 0 && ( + {outcomeInfos.name} + + {(encounterResult.dmgDealt.length > 0 || + encounterResult.dmgTaken.length > 0 || + (encounterResult.action === EncountersAction.Run && encounterResult.drugLoss.length > 0)) && ( + + + {/* {encounterResult.rounds > 0 && ( After {encounterResult.rounds} attempt{encounterResult.rounds > 1 ? "s" : ""} - )} - {outcomeInfos.description && `* ${outcomeInfos.description} *`} + )} */} + {[...Array(encounterResult.rounds)].map((i, idx) => { + return ( + <> + {encounterResult.dmgDealt[idx] && ( + + You hit for {encounterResult.dmgDealt[idx][0]} DMG{" "} + {encounterResult.dmgDealt[idx][1] > 0 && <>(+{encounterResult.dmgDealt[idx][1]})} + + } + /> + )} + + {encounterResult.dmgTaken[idx] && ( + } + text={ + + You took {encounterResult.dmgTaken[idx][0]} DMG{" "} + {encounterResult.dmgTaken[idx][1] > 0 && <>(-{encounterResult.dmgTaken[idx][1]})} + + } + /> + )} + + {encounterResult.drugLoss[idx] && ( + + You lost {encounterResult.drugLoss[idx]}{" "} + {configStore.getDrugById(encounterResult.drugId).name} on the run + + } + /> + )} + + ); + })} + + {encounterResult.escapedWithItem && ( + Your {game.items.speed.base.name} was decisive on this run} + /> + )} + + + )} + + {/* {encounterResult.rounds > 0 && } */} + + + {/* {outcomeInfos.getResponse(true)} */} + + {/* RESULT */} + + + {outcomeInfos.description && `* ${outcomeInfos.description} *`} + + {encounterResult.cashEarnt > 0 && ( - {`You confiscated ${formatCash(encounterResult.cashEarnt)}`} + {`You confiscated ${formatCash( + encounterResult.cashEarnt, + )}`} )} - {encounterResult.cashLoss > 0 && Cash loss : {formatCash(encounterResult.cashLoss)}} - {encounterResult.dmgTaken > 0 && Lost {encounterResult.dmgTaken} HP} - {encounterResult.dmgDealt > 0 && Dealt {encounterResult.dmgDealt} DMG} - {encounterResult.drugLoss > 0 && ( - - Lost {encounterResult.drugLoss} {configStore.getDrugById(encounterResult.drugId).name} + + {encounterResult.cashLoss > 0 && ( + + You lost {formatCash(encounterResult.cashLoss)} )} + + {encounterResult.action === EncountersAction.Pay && + encounterResult.drugLoss.reduce((p, c) => p + c, 0) > 0 && ( + + You lost {encounterResult.drugLoss.reduce((p, c) => p + c, 0)}{" "} + {configStore.getDrugById(encounterResult.drugId).name} + + )} + {encounterResult.turnLoss > 0 && ( You spent {encounterResult.turnLoss} day{encounterResult.turnLoss > 1 ? "s" : ""} in{" "} - {outcomeInfos.encounterOutcome === EncounterOutcomes.Hospitalized ? "the hospital" : "in jail"}! + {outcomeInfos.encounterOutcome === EncounterOutcomes.Hospitalized ? "the hospital" : "jail"}! )} - - {/* {JSON.stringify(encounterResult, null, 2)} */} @@ -121,4 +197,15 @@ export default function Consequence() { ); -} +}; + +export default observer(Consequence); + +const Line = ({ icon, text }: { icon: ReactNode; text: ReactNode }) => { + return ( + + {icon} + {text} + + ); +}; diff --git a/web/src/pages/[gameId]/event/decision.tsx b/web/src/pages/[gameId]/event/decision.tsx index 39e10627..11667bc6 100644 --- a/web/src/pages/[gameId]/event/decision.tsx +++ b/web/src/pages/[gameId]/event/decision.tsx @@ -48,11 +48,10 @@ const Decision = observer(() => { useEffect(() => { if (game && gameEvents && !isPending) { - const lastEncounter = gameEvents.getLastEncounter(); - const encounter = lastEncounter!.parsed as TravelEncounterData; + const encounter = gameEvents?.lastEncounter!.parsed as TravelEncounterData; setEncounter(encounter); } - }, [game, isPending, gameEvents]); + }, [game, isPending, gameEvents, gameEvents?.lastEncounter]); useEffect(() => { if (game && gameEvents && encounter && !isPending) { diff --git a/web/src/pages/[gameId]/logs.tsx b/web/src/pages/[gameId]/logs.tsx index 079d7f94..10021dee 100644 --- a/web/src/pages/[gameId]/logs.tsx +++ b/web/src/pages/[gameId]/logs.tsx @@ -15,7 +15,14 @@ import { UpgradeItemData, } from "@/dojo/events"; import { WorldEvents } from "@/dojo/generated/contractEvents"; -import { encountersActionName, encountersActionNameKeys, outcomeNames, outcomeNamesKeys, reputationRanks, reputationRanksKeys } from "@/dojo/helpers"; +import { + encountersActionName, + encountersActionNameKeys, + outcomeNames, + outcomeNamesKeys, + reputationRanks, + reputationRanksKeys, +} from "@/dojo/helpers"; import { useConfigStore, useDojoContext, useGameStore, useRouterContext } from "@/dojo/hooks"; import { ConfigStore, LocationConfigFull } from "@/dojo/stores/config"; import { EncounterOutcomes, Encounters, EncountersAction, ItemSlot } from "@/dojo/types"; @@ -32,13 +39,6 @@ import { TabPanels, Tabs, Text, - Tooltip, - UnorderedList, - VStack -} from "@chakra-ui/react"; -import { observer } from "mobx-react-lite"; -import { useEffect, useRef, useState } from "react"; -import { shortString } from "starknet"; Tooltip, UnorderedList, VStack, @@ -298,7 +298,9 @@ function renderTravelEncounter(log: TravelEncounterData, dayLog: LogByDay, key: : ""; const action = lastEncouterResult?.action; - const totalHpLoss = lastEncouterResult ? log.healthLoss + lastEncouterResult?.dmgTaken : log.healthLoss; + const totalHpLoss = lastEncouterResult + ? log.healthLoss + lastEncouterResult?.dmgTaken.map((i) => i[0]).reduce((p, c) => p + c, 0) + : log.healthLoss; return ( 0) { setResultTooltip(`- ${formatCash(resultInfos.cashLoss)}`); } else { - setResultTooltip(`- ${resultInfos.drugLoss} Drugs`); + setResultTooltip(`- ${resultInfos.drugLoss.reduce((p, c) => p + c, 0)} Drugs`); } } else { setResultTooltip(""); diff --git a/web/src/pages/index.tsx b/web/src/pages/index.tsx index 036b2d34..7be77d17 100644 --- a/web/src/pages/index.tsx +++ b/web/src/pages/index.tsx @@ -18,7 +18,6 @@ export default function Home() { account, burner: { create: createBurner, clear: clearBurner, isDeploying: isBurnerDeploying }, } = useDojoContext(); - const { toast } = useToast(); const [isSubmitting, setIsSubmitting] = useState(false); @@ -63,7 +62,7 @@ export default function Home() { return ( - + {isGated ? (