Game-Server/API/models/Player.js
2026-01-24 16:47:19 -04:00

170 lines
4.6 KiB
JavaScript

const mongoose = require('mongoose');
const { calculateXPToNextLevel, getLevelFromXP } = require('../config/xp-progression');
const playerSchema = new mongoose.Schema({
userId: {
type: String,
required: true,
unique: true
},
username: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
// Authentication
password: {
type: String,
required: true,
select: false // Don't include password in queries by default
},
// Player stats
stats: {
level: { type: Number, default: 1 },
experience: { type: Number, default: 0 },
totalXP: { type: Number, default: 0 }, // Total accumulated XP across all levels
experienceToNext: { type: Number, default: function() { return calculateXPToNextLevel(1, 0); } },
credits: { type: Number, default: 1000 },
dungeonsCleared: { type: Number, default: 0 },
playTime: { type: Number, default: 0 },
lastLogin: { type: Date, default: Date.now }
},
// Base attributes
attributes: {
health: { type: Number, default: 100 },
maxHealth: { type: Number, default: 100 },
energy: { type: Number, default: 100 },
maxEnergy: { type: Number, default: 100 },
attack: { type: Number, default: 10 },
defense: { type: Number, default: 5 },
speed: { type: Number, default: 10 },
criticalChance: { type: Number, default: 0.05 },
criticalDamage: { type: Number, default: 1.5 }
},
// Player info
info: {
name: { type: String, default: 'Commander' },
title: { type: String, default: 'Rookie Pilot' },
guild: { type: String, default: null },
rank: { type: String, default: 'Cadet' }
},
// Current ship
currentShip: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Ship'
},
// Settings
settings: {
autoSave: { type: Boolean, default: true },
notifications: { type: Boolean, default: true },
soundEffects: { type: Boolean, default: true },
music: { type: Boolean, default: false },
discordIntegration: { type: Boolean, default: false }
},
// Daily rewards
dailyRewards: {
lastClaim: { type: Date, default: null },
consecutiveDays: { type: Number, default: 0 }
},
// Server info
currentServer: { type: String, default: null },
// Timestamps
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now }
}, {
timestamps: true
});
// Indexes for performance (only for non-unique fields)
playerSchema.index({ 'stats.level': 1 });
playerSchema.index({ currentServer: 1 });
// Methods
playerSchema.methods.addExperience = function(amount) {
// Add to total accumulated XP
this.stats.totalXP += amount;
// Calculate new level based on total XP
const levelInfo = getLevelFromXP(this.stats.totalXP);
const oldLevel = this.stats.level;
this.stats.level = levelInfo.level;
this.stats.experience = levelInfo.xpIntoLevel;
this.stats.experienceToNext = levelInfo.xpToNext;
// Return whether the player leveled up
return this.stats.level > oldLevel;
};
playerSchema.methods.addCredits = function(amount) {
this.stats.credits += amount;
return this.stats.credits;
};
playerSchema.methods.canAfford = function(cost) {
return this.stats.credits >= cost;
};
playerSchema.methods.spendCredits = function(cost) {
if (this.canAfford(cost)) {
this.stats.credits -= cost;
return true;
}
return false;
};
playerSchema.methods.updatePlayTime = function(sessionTime) {
this.stats.playTime += sessionTime;
this.stats.lastLogin = new Date();
};
playerSchema.methods.claimDailyReward = function() {
const today = new Date();
const lastClaim = this.dailyRewards.lastClaim;
// Check if already claimed today
if (lastClaim && lastClaim.toDateString() === today.toDateString()) {
return { success: false, message: 'Daily reward already claimed today' };
}
// Check consecutive days
const yesterday = new Date(today);
yesterday.setDate(yesterday.getDate() - 1);
if (lastClaim && lastClaim.toDateString() === yesterday.toDateString()) {
this.dailyRewards.consecutiveDays += 1;
} else {
this.dailyRewards.consecutiveDays = 1;
}
this.dailyRewards.lastClaim = today;
// Calculate reward based on consecutive days
const baseReward = 100;
const consecutiveBonus = (this.dailyRewards.consecutiveDays - 1) * 50;
const totalReward = baseReward + consecutiveBonus;
this.addCredits(totalReward);
return {
success: true,
reward: totalReward,
consecutiveDays: this.dailyRewards.consecutiveDays
};
};
module.exports = mongoose.model('Player', playerSchema);