diff --git a/src/modules/game/game.ts b/src/modules/game/game.ts index 9bfafc3..02cbe82 100644 --- a/src/modules/game/game.ts +++ b/src/modules/game/game.ts @@ -4,9 +4,13 @@ import { config } from "../../config.js"; import { getPlayerById, getRace } from "../../services/game/entity.js"; import { getLocation, + getLocationByName, getLocationDistance, + getParentLocation, + hasLocation, + startTravel, } from "../../services/game/location.js"; -import { getLevel } from "../../services/game/game.js"; +import { getLevel } from "../../services/game/entity.js"; import { getFullItemName, getTotalStats, @@ -44,6 +48,10 @@ const registerModuleGame = ( startConditions: [`${gamePrefix} nearby`], callbackFunc: onNearby, }); + callbackStore.messageCallbacks.push({ + startConditions: [`${gamePrefix} travel`], + callbackFunc: onTravel, + }); }; const onHelp = (_text: string, roomId: string) => { @@ -57,7 +65,7 @@ const onHelp = (_text: string, roomId: string) => {
  • !game inventory {index} - Shows information about an item in your inventory
  • !game location - Shows information about your current location
  • !game nearby - Shows nearby locations
  • -
  • (WIP) !game travel {location} - Travel to a location
  • +
  • !game travel {location} - Travel to a location
  • (WIP) !game talk {entity} - Talk to an entity
  • (WIP) !game fight {entity} - Fight an entity
  • (WIP) !game work {action} - Start work
  • @@ -193,8 +201,35 @@ const onNearby = (_text: string, roomId: string, sender: string) => { `

    There are ${location.childLocations.length} locations around you (${player.name})

    `, ); }; +const onTravel = (text: string, roomId: string, sender: string) => { + const player = getPlayerById(sender); + + const locationName = text.replace(`${gamePrefix} travel `, "").trim(); + const location = getLocationByName(locationName); + if (!location) { + client.sendTextMessage(roomId, "No such location exists"); + return; + } + + const currentLocationHasLocation = hasLocation( + player.location, + location.id, + ); + const parentLocationHasLocation = hasLocation( + getParentLocation(player.location).id, + location.id, + ); + if (!currentLocationHasLocation && !parentLocationHasLocation) { + client.sendTextMessage(roomId, "No such location found nearby"); + return; + } + + startTravel(player, location.id, client, roomId); +}; + export { registerModuleGame }; diff --git a/src/services/game/entity.ts b/src/services/game/entity.ts index 80973e0..185cd00 100644 --- a/src/services/game/entity.ts +++ b/src/services/game/entity.ts @@ -1,9 +1,10 @@ import { getUserNameById } from "../../helpers.js"; import { state } from "../../store/store.js"; -import type { IPlayer } from "./structures/entities.js"; +import type { IEntity, IPlayer } from "./structures/entities.js"; import { itemShortsword } from "./structures/items.js"; import { Location } from "./structures/locations.js"; import { Race, raceHuman, races, type IRace } from "./structures/races.js"; +import type { ILevel } from "./types.js"; const createPlayer = (name: string): IPlayer => ({ name: name, @@ -49,4 +50,27 @@ const getRace = (id: Race): IRace => { return race ? race : raceHuman; }; -export { createPlayer, getPlayerById, getPlayer, getRace }; +const getLevel = (experience: number): ILevel => { + let tmpExperience = experience; + let experienceToNextLevel = 50; + let level = 0; + + while (tmpExperience >= experienceToNextLevel) { + level++; + tmpExperience -= experienceToNextLevel; + experienceToNextLevel = experienceToNextLevel *= 1.25; + } + + return { + level: level, + totalExperience: Math.floor(experience), + experienceInLevel: Math.floor(tmpExperience), + experienceToNextLevel: Math.floor(experienceToNextLevel), + }; +}; + +const getSpeed = (entity: IEntity) => { + return 1 + Math.sqrt(entity.agility + entity.endurance) / 3; +}; + +export { createPlayer, getPlayerById, getPlayer, getRace, getLevel, getSpeed }; diff --git a/src/services/game/game.ts b/src/services/game/game.ts index 6e64232..473a0f4 100644 --- a/src/services/game/game.ts +++ b/src/services/game/game.ts @@ -1,22 +0,0 @@ -import type { ILevel } from "./types.js"; - -const getLevel = (experience: number): ILevel => { - let tmpExperience = experience; - let experienceToNextLevel = 50; - let level = 0; - - while (tmpExperience >= experienceToNextLevel) { - level++; - tmpExperience -= experienceToNextLevel; - experienceToNextLevel = experienceToNextLevel *= 1.25; - } - - return { - level: level, - totalExperience: Math.floor(experience), - experienceInLevel: Math.floor(tmpExperience), - experienceToNextLevel: Math.floor(experienceToNextLevel), - }; -}; - -export { getLevel }; diff --git a/src/services/game/location.ts b/src/services/game/location.ts index 9e1b556..b30e890 100644 --- a/src/services/game/location.ts +++ b/src/services/game/location.ts @@ -1,9 +1,12 @@ +import type { MatrixClient } from "matrix-js-sdk"; import { + Location, locationFarlands, locations, type ILocation, - type Location, } from "./structures/locations.js"; +import type { IPlayer } from "./structures/entities.js"; +import { getSpeed } from "./entity.js"; const getLocation = (id: Location): ILocation => { const location = locations.find((location) => location.id === id); @@ -11,6 +14,14 @@ const getLocation = (id: Location): ILocation => { return location ? location : locationFarlands; }; +const getLocationByName = (name: string): ILocation => { + const location = locations.find( + (location) => location.name.toLowerCase() === name.toLowerCase(), + ); + + return location ? location : locationFarlands; +}; + const getLocationDistance = ( locationA: ILocation, locationB: ILocation, @@ -23,4 +34,62 @@ const getLocationDistance = ( return Math.sqrt(deltaPow); }; -export { getLocation, getLocationDistance }; +const getParentLocation = (childLocation: Location): ILocation => { + const parentLocation = locations.find((location) => + location.childLocations.includes(childLocation), + ); + + return parentLocation ? parentLocation : locationFarlands; +}; + +const hasLocation = ( + locationParent: Location, + locationChild: Location, +): boolean => { + const childLocations = getLocation(locationParent).childLocations; + + return childLocations.includes(locationChild); +}; + +const startTravel = ( + player: IPlayer, + location: Location, + client: MatrixClient, + roomId: string, +) => { + const currentLocation = getLocation(player.location); + const newLocation = getLocation(location); + + const distance = getLocationDistance(currentLocation, newLocation); + + setTimeout( + () => { + finishTravel(player, newLocation, client, roomId); + }, + (distance / getSpeed(player)) * 3600000, + ); +}; + +const finishTravel = ( + player: IPlayer, + location: ILocation, + client: MatrixClient, + roomId: string, +) => { + player.location = location.id; + + client.sendTextMessage( + roomId, + `${player.name} has arrived to ${location.name}`, + ); +}; + +export { + getLocation, + getLocationByName, + getLocationDistance, + getParentLocation, + hasLocation, + startTravel, + finishTravel, +};