programming-game
Version:
The client for programming game, an mmorpg that you interact with entirely through code.
337 lines (331 loc) • 9.72 kB
text/typescript
import { Items, UsableItems, Equipments } from "./items";
import { recipes } from "./recipes";
import { Spells, CastIntent } from "./spells";
import {
ClientSidePlayer,
ROLES,
SetRoleIntent,
IntentType,
ClientSideUnit,
AttackIntent,
Tree,
MiningNode,
HarvestIntent,
MoveIntent,
RespawnIntent,
SummonManaIntent,
EatIntent,
SellItemsIntent,
BuyItemsIntent,
UseIntent,
SeekPartyIntent,
InviteToPartyIntent,
LeavePartyIntent,
AcceptPartyInviteIntent,
DeclinePartyInviteIntent,
PlayerEquipment,
EquipIntent,
UnequipIntent,
CraftIntent,
WeaponSkillIntent,
DropIntent,
NewTrades,
SetTradeIntent,
ClientSideNPC,
AcceptQuestIntent,
AbandonQuestIntent,
TurnInQuestIntent,
Inventory,
WithdrawIntent,
DepositIntent,
EquipSpellIntent,
UnequipSpellIntent,
Position,
} from "./types";
import { entries } from "./utils";
import { WeaponSkill, WeaponSkillSpecifics } from "./weapon-skills";
export const getHandlers = (player: ClientSidePlayer) => {
const handlers = {
/**
* Update the role that you intend to play when grouping with other players.
*/
setRole: (role: ROLES): SetRoleIntent => {
return { type: IntentType.setRole, role };
},
/**
* Move to and attack a unit.
*/
attack: (target: ClientSideUnit): AttackIntent => {
return { type: IntentType.attack, target: target.id };
},
/**
* Attempt to harvest resources from a tree or mining node.
*/
harvest: (target: Tree | MiningNode): HarvestIntent => {
return {
type: IntentType.harvest,
target: target.id,
};
},
/**
* Move to the specified position.
* @param position {Position} The position to move to.
*/
move: (position: Position): MoveIntent => {
return { type: IntentType.move, position };
},
/**
* Respawn a your character after death.
*
* Respawning will place your character at the nearest respawn point, but you'll lose all your items and equipment.
*/
respawn: (): RespawnIntent => {
return { type: IntentType.respawn } as RespawnIntent;
},
/**
* Concentrate and restore your mana more quickly than normal.
*/
summonMana: (): SummonManaIntent => {
return { type: IntentType.summonMana };
},
/**
* Attempt to eat an item from your inventory.
*/
eat: (item: Items): EatIntent => {
return {
type: IntentType.eat,
item: item,
save: (player.inventory[item] || 0) - 1,
};
},
/**
* Cast a spell at an optional target.
*
* Spells require that the appropriate spell stone is equipped in your spellbook AND that you have enough spell slots in your equipment.
*/
cast: (spell: Spells, target?: ClientSideUnit): CastIntent => {
return { type: IntentType.cast, spell, target: target?.id };
},
/**
* Sell items from your inventory to an NPC or player.
*/
sell: (opt: {
items: { [key in Items]?: number };
to: ClientSideUnit;
}): SellItemsIntent => {
return {
type: IntentType.sellItems,
items: entries(opt.items).reduce((acc, [item, amount]) => {
const until = (player.inventory[item] || 0) - (amount || 0);
acc[item] = until;
return acc;
}, {} as { [key in Items]: number }),
to: opt.to.id,
};
},
/**
* Buy items from an NPC or player.
*
* The target unit must have the items available to sell, and listed in their trades.
*/
buy: (opts: {
items: { [key in Items]?: number };
from: ClientSideUnit;
}): BuyItemsIntent => {
return {
type: IntentType.buyItems,
items: entries(opts.items).reduce((acc, [item, amount]) => {
if (!amount) return acc;
const until = amount + (player.inventory[item] || 0);
if (amount) {
acc[item] = until;
}
return acc;
}, {} as { [key in Items]: number }),
from: opts.from.id,
};
},
/**
* Use an item from your inventory, optionally you can use the item on a target unit instead of yourself.
*/
use: (item: UsableItems, target?: ClientSideUnit): UseIntent => {
return {
type: IntentType.use,
item,
until: (player.inventory[item] || 0) - 1,
target: target?.id,
};
},
/**
* Announce to the world that you are seeking a party.
*/
seekParty: (): SeekPartyIntent => {
return { type: IntentType.seekParty };
},
/**
* Invite the specified player id to join your party.
*/
inviteToParty: (playerId: string): InviteToPartyIntent => {
return { type: IntentType.inviteToParty, playerId };
},
/**
* Leave your current party.
*/
leaveParty: (): LeavePartyIntent => {
return { type: IntentType.leaveParty };
},
/**
* Accept a party invitation from the specified player id.
*
* This is a noop if the player hasn't invited you to a party.
*/
acceptPartyInvite: (playerId: string): AcceptPartyInviteIntent => {
return { type: IntentType.acceptPartyInvite, playerId };
},
/**
* Decline a party invitation from the specified player id.
*/
declinePartyInvite: (playerId: string): DeclinePartyInviteIntent => {
return { type: IntentType.declinePartyInvite, playerId };
},
/**
* Equip a piece of equipment into the specified slot.
*
* The item must be in your inventory.
*/
equip: (item: Equipments, slot: keyof PlayerEquipment): EquipIntent => {
return { type: IntentType.equip, item, slot };
},
/**
* Return a piece of equipment from your equipment back into your inventory.
*/
unequip: (slot: keyof PlayerEquipment): UnequipIntent => {
return { type: IntentType.unequip, slot };
},
/**
* Attempt to craft an item using materials from your inventory.
*/
craft: (
item: keyof typeof recipes,
from: Partial<Record<Items, number>>
): CraftIntent => {
return { type: IntentType.craft, item, from };
},
/**
* Consumes TP to use a weapon skill on a target.
*
* Some weapon skills may require additional options.
*/
useWeaponSkill: <T extends WeaponSkill>(
specifics: WeaponSkillSpecifics[T]["client"]
): WeaponSkillIntent<T> => {
if (specifics.skill === "misdirectingShot") {
return {
type: IntentType.weaponSkill,
skill: specifics.skill,
target: specifics.target.id,
options: {
to: specifics.target.id,
},
};
}
return {
type: IntentType.weaponSkill,
skill: specifics.skill,
target: specifics.target.id,
};
},
/**
* Drop items from your inventory onto the ground.
*/
drop: ({ item, amount }: { item: Items; amount: number }): DropIntent => {
return {
type: IntentType.drop,
item,
until: (player.inventory[item] || 0) - amount,
};
},
/**
* Update the list of items that you are buying an selling as well as their prices.
*/
setTrade: (trades: NewTrades): SetTradeIntent => {
return {
type: IntentType.setTrade,
trades,
};
},
/**
* Accept a quest from an NPC.
*/
acceptQuest: (npc: ClientSideNPC, questId: string): AcceptQuestIntent => {
return { type: IntentType.acceptQuest, npcId: npc.id, questId };
},
/**
* Remove a quest from your active quests and free up a slot in your quest log.
*/
abandonQuest: (questId: string): AbandonQuestIntent => {
return { type: IntentType.abandonQuest, questId };
},
/**
* Turn in a completed quest to an NPC.
*/
turnInQuest: (npc: ClientSideNPC, questId: string): TurnInQuestIntent => {
return { type: IntentType.turnInQuest, npcId: npc.id, questId };
},
/**
* Withdraw items from a storage NPC to your inventory.
*
* The specified NPC MUST be a banker.
*/
withdraw: (npc: ClientSideNPC, items: Inventory): WithdrawIntent => {
const until: Inventory = {};
entries(items).forEach(([item, amount = 0]) => {
const charAmount = player.storage[item] || 0;
until[item] = charAmount - amount;
});
return {
type: IntentType.withdraw,
npcId: npc.id,
until,
};
},
/**
* Deposit items from your inventory into a storage NPC.
*
* The specified NPC MUST be a banker.
*/
deposit: (npc: ClientSideNPC, items: Inventory): DepositIntent => {
const until: Inventory = {};
entries(items).forEach(([item, amount = 0]) => {
const charAmount = player.inventory[item] || 0;
until[item] = charAmount - amount;
});
return {
type: IntentType.deposit,
npcId: npc.id,
until,
};
},
/**
* Equips the specified spell stone from your inventory into your spellbook.
*
* You MUST have an open slot if your spellbook, and the spell stone must be in your inventory.
*/
equipSpell: (spell: Spells): EquipSpellIntent => {
return {
type: IntentType.equipSpell,
spell,
};
},
/**
* Unequips the first spell in the player's spellbook, and returns it to your inventory.
*/
unequipSpell: (): UnequipSpellIntent => {
return {
type: IntentType.unequipSpell,
};
},
};
return handlers;
};
export type Handlers = ReturnType<typeof getHandlers>;