after play-testing, its come up that the stamina mechanic is just confusing players.
it is called "vigor", which most games don't use, It regens too quicklt to actually
slow user actions down. The whole game is an active pbbg, so restricting actions
that the player has to manually do is just not fun.
--- /dev/null
+import { Knex } from "knex";
+
+export async function up(knex: Knex): Promise<void> {
+ await knex.schema.alterTable('players', table => {
+ table.dropColumn('stamina');
+ });
+}
+
+export async function down(knex: Knex): Promise<void> {
+ await knex.schema.alterTable('players', table => {
+ table.integer('stamina').defaultTo(0);
+ });
+}
expToLevel,
maxHp,
totalDefence,
- maxVigor,
baseDamage,
} from "../shared/player";
import { clearTravelPlan } from "./map";
}
}
- // @TODO implement flee based on dex + vigor
+ // @TODO implement flee based on dex
if (data.action === "flee") {
roundData.roundDetails.push(
`You managed to escape from the ${monster.name}!`
);
player.hp = maxHp(player.constitution, player.level);
- player.vigor = maxVigor(player.constitution, player.level);
}
// get the monster location if it was an EXPLORED fight
if (roundData.fightTrigger === "explore") {
});
}
- player.vigor -= 1;
- if (player.vigor < 0) {
- player.vigor = 0;
- }
-
const unequippedItems = await updateAp(
player.id,
1,
if (player.hp <= 0) {
player.hp = 0;
- player.vigor = 0;
roundData.winner = "monster";
roundData.roundDetails.push(`You were killed by the ${monster.name}`);
import { db } from './lib/db';
-import {Player, maxHp, maxVigor} from "@shared/player";
+import {Player, maxHp} from "@shared/player";
import { random } from 'lodash';
import { Skills } from '@shared/skills';
import {Profession} from '@shared/profession';
};
raw.hp = maxHp(raw.constitution, 1);
- raw.vigor = maxVigor(raw.constitution, 1);
const res = await db('players').insert(raw).returning<Player[]>('*');
const player = res.pop();
id: player.id
}).update({
hp: player.hp,
- vigor: player.vigor,
strength: player.strength,
constitution: player.constitution,
dexterity: player.dexterity,
import { createFight, loadMonster } from "../../monster";
import { renderFightPreRoundDungeon } from "../../views/fight";
import { has, max, each } from 'lodash';
-import { expToLevel, maxHp, maxVigor } from "../../../shared/player";
+import { expToLevel, maxHp} from "../../../shared/player";
import { updatePlayer } from "../../player";
import { getEventHistoryToday } from "../../events";
req.player.level++;
req.player.stat_points += req.player.profession === 'Wanderer' ? 1 : 2;
req.player.hp = maxHp(req.player.constitution, req.player.level);
- req.player.vigor = maxVigor(req.player.constitution, req.player.level);
}
// delete the tracking for this dungeon-run
import { Request, Response, Router } from "express";
-import { maxHp, maxVigor } from "../../../shared/player";
+import { maxHp} from "../../../shared/player";
import { authEndpoint } from '../../auth';
import { updatePlayer } from "../../player";
import { getCityDetails, getService } from '../../map';
text.push(`<p>"${getText('intro', service, city)}"</p>`);
- if(req.player.hp === maxHp(req.player.constitution, req.player.level) && req.player.vigor === maxVigor(req.player.constitution, req.player.level)) {
+ if(req.player.hp === maxHp(req.player.constitution, req.player.level)) {
text.push(`<p>You're already in peak condition!</p>`);
}
else {
}
else {
req.player.hp = maxHp(req.player.constitution, req.player.level);
- req.player.vigor = maxVigor(req.player.constitution, req.player.level);
req.player.gold -= cost;
await updatePlayer(req.player);
import { authEndpoint } from '../auth';
import { getEquippedItems } from '../inventory';
import { updatePlayer } from '../player';
-import {maxHp, maxVigor } from '../../shared/player';
+import {maxHp} from '../../shared/player';
import * as Alert from '../views/alert';
import { renderPlayerBar } from '../views/player-bar'
import { renderProfilePage } from '../views/profile';
req.player[stat]++;
req.player.hp = maxHp(req.player.constitution, req.player.level);
- req.player.vigor = maxVigor(req.player.constitution, req.player.level);
updatePlayer(req.player);
res.send(renderPlayerBar(req.player) + renderProfilePage(req.player, equipment));
-import { expToLevel, maxHp, maxVigor, Player } from "@shared/player";
+import { expToLevel, maxHp, Player } from "@shared/player";
import { ProgressBar } from "./components/progress-bar";
function displayLoginSignupForm(): string {
<div class="gold">${player.gold.toLocaleString()}</div>
</div>
${ProgressBar(player.hp, maxHp(player.constitution, player.level), 'hp-bar', { endingColor: '#ff7070', startingColor: '#d62f2f', title: 'HP', displayPercent: true })}
- ${ProgressBar(player.vigor, maxVigor(player.constitution, player.level), 'vigor-bar', { endingColor: '#5ebb5e', startingColor: '#7be67b', title: 'Vigor', displayPercent: true})}
${ProgressBar(player.exp, expToLevel(player.level + 1), 'exp-bar', { endingColor: '#5997f9', startingColor: '#1d64d4', title: 'EXP', displayPercent: true})}
</div>
${player.account_type === 'session' ? displayLoginSignupForm() : ''}
import { EquippedItemDetails } from "@shared/equipped";
-import { expToLevel, maxHp, maxVigor, Player, StatDef, StatDisplay, totalDefence } from "@shared/player";
+import { expToLevel, maxHp, Player, StatDef, StatDisplay, totalDefence } from "@shared/player";
function statPointIncreaser(stat: StatDisplay) {
return `<button class="increase-stat" hx-post="/player/stat/${stat.id}" hx-target="#profile">+</button>`;
<th title="The total amount of damage you can take before you pass out" tabindex="0" class="tooltip">HP</th>
<td>${player.hp.toLocaleString()}/${maxHp(player.constitution, player.level).toLocaleString()}</td>
</tr>
- <tr>
- <th title="Your energy level. Low vigor will cause your overall defence and damage to drop." tabindex="0" class="tooltip">Vigor</th>
- <td>${player.vigor.toLocaleString()}/${maxVigor(player.constitution, player.level).toLocaleString()}</td>
- </tr>
<tr>
<th title="How many experience points you need to get to your next level" tabindex="0" class="tooltip">EXP</th>
<td>${player.exp.toLocaleString()}/${expToLevel(player.level + 1).toLocaleString()}</td>
</tr>
<tr>
- <th title="The max defence you can have (and your true defence affected by your vigor)" tabindex="0" class="tooltip">Defence</th>
- <td>${totalDefence(equipment, player, false).toLocaleString()} (${totalDefence(equipment, player).toLocaleString()})</td>
+ <th title="The max defence you can have" tabindex="0" class="tooltip">Defence</th>
+ <td>${totalDefence(equipment, player).toLocaleString()} (${totalDefence(equipment, player).toLocaleString()})</td>
</tr>
<tr>
<th title="You can use these to increase the base stats below" tabindex="0" class="tooltip">Stat Points</th>
constitution: number;
dexterity: number;
intelligence: number;
- stamina: number;
exp: number;
level: number;
gold: number;
hp: number;
city_id: number;
stat_points: number;
- vigor: number;
permissions: Permission[]
}
return Math.ceil((constitution * 1.7) + (playerLevel * 1.3));
}
-export function maxVigor(constitution: number, playerLevel: number): number {
- return Math.ceil((constitution * 3.8) + (playerLevel * 1.5));
-}
-
export function expToLevel(level: number): number {
if(level < 10) {
return level * 10 - 10;
}
}
-export function totalDefence(equippedItems: EquippedItemDetails[], player: Player, accountForVigor: boolean = true): number {
- const vigorPercent = player.vigor / maxVigor(player.constitution, player.level);
-
+export function totalDefence(equippedItems: EquippedItemDetails[], player: Player): number {
const totalDefence = equippedItems.reduce((acc, curr) => {
let defence = curr.boosts.defence ?? 0;
return acc += defence;
}, 0);
- if(accountForVigor) {
- return Math.ceil(totalDefence * vigorPercent);
- }
- else {
- return totalDefence;
- }
+ return totalDefence;
}
export function baseDamage(statValue: number, boostStat: number, damage: number): number {
id: Stat.constitution,
display: 'Constitution',
abbrv: 'CON',
- description: 'Affects your max HP and Vigor'
+ description: 'Affects your max HP'
});
StatDef.set(Stat.dexterity, {