Add skill management system: implement Skill and PetSkill models, create SkillController, and update ApplicationDbContext for skills
This commit is contained in:
parent
06455db598
commit
f234b5d84d
43
Controllers/SkillController.cs
Normal file
43
Controllers/SkillController.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using PetCompanion.Services;
|
||||||
|
|
||||||
|
namespace PetCompanion.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/v1/[controller]")]
|
||||||
|
public class SkillController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly SkillService _skillService;
|
||||||
|
private readonly ILogger<SkillController> _logger;
|
||||||
|
private Guid userId = Guid.Parse("f5f4b3b3-3b7b-4b7b-8b7b-7b7b7b7b7b7b");
|
||||||
|
|
||||||
|
public SkillController(
|
||||||
|
ILogger<SkillController> logger,
|
||||||
|
SkillService skillService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_skillService = skillService;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetAvailableSkills()
|
||||||
|
{
|
||||||
|
var skills = await _skillService.GetAvailableSkills();
|
||||||
|
return Ok(skills);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("{petId}/allocate/{skillId}")]
|
||||||
|
public async Task<IActionResult> AllocateSkillPoint(string petId, int skillId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _skillService.AllocateSkillPoint(petId, userId.ToString(), skillId);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,9 @@ namespace PetCompanion.Data
|
|||||||
public DbSet<Pet> Pets { get; set; }
|
public DbSet<Pet> Pets { get; set; }
|
||||||
public DbSet<PetStats> PetStats { get; set; }
|
public DbSet<PetStats> PetStats { get; set; }
|
||||||
public DbSet<Resources> Resources { get; set; }
|
public DbSet<Resources> Resources { get; set; }
|
||||||
|
public DbSet<Skill> Skills { get; set; }
|
||||||
|
public DbSet<SkillEffect> SkillEffects { get; set; }
|
||||||
|
public DbSet<PetSkill> PetSkills { get; set; }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
@ -29,6 +32,32 @@ namespace PetCompanion.Data
|
|||||||
.HasConversion(
|
.HasConversion(
|
||||||
v => v != DateTime.MinValue ? v.ToUniversalTime() : v,
|
v => v != DateTime.MinValue ? v.ToUniversalTime() : v,
|
||||||
v => v != DateTime.MinValue ? DateTime.SpecifyKind(v, DateTimeKind.Utc) : v);
|
v => v != DateTime.MinValue ? DateTime.SpecifyKind(v, DateTimeKind.Utc) : v);
|
||||||
|
|
||||||
|
modelBuilder.Entity<PetSkill>()
|
||||||
|
.HasOne(ps => ps.Pet)
|
||||||
|
.WithMany(p => p.Skills)
|
||||||
|
.HasForeignKey(ps => ps.PetId);
|
||||||
|
|
||||||
|
modelBuilder.Entity<PetSkill>()
|
||||||
|
.HasOne(ps => ps.Skill)
|
||||||
|
.WithMany(s => s.PetSkills)
|
||||||
|
.HasForeignKey(ps => ps.SkillId);
|
||||||
|
|
||||||
|
modelBuilder.Entity<SkillEffect>()
|
||||||
|
.HasOne(se => se.Skill)
|
||||||
|
.WithMany(s => s.Effects)
|
||||||
|
.HasForeignKey(se => se.SkillId);
|
||||||
|
|
||||||
|
// Seed initial skills
|
||||||
|
var skills = SkillsData.GetInitialSkills();
|
||||||
|
foreach (var skill in skills)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<Skill>().HasData(skill);
|
||||||
|
foreach (var effect in skill.Effects)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<SkillEffect>().HasData(effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
273
Data/SkillsData.cs
Normal file
273
Data/SkillsData.cs
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
using PetCompanion.Models;
|
||||||
|
|
||||||
|
namespace PetCompanion.Data
|
||||||
|
{
|
||||||
|
public static class SkillsData
|
||||||
|
{
|
||||||
|
public static IEnumerable<Skill> GetInitialSkills()
|
||||||
|
{
|
||||||
|
return new List<Skill>
|
||||||
|
{
|
||||||
|
new Skill
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
Name = "Vitality Mastery",
|
||||||
|
Description = "Increases maximum health of your pet, making it more resilient.",
|
||||||
|
Type = SkillType.GROUND,
|
||||||
|
PointsCost = 1,
|
||||||
|
Icon = "❤",
|
||||||
|
SkillsIdRequired = null,
|
||||||
|
Effects = new List<SkillEffect>
|
||||||
|
{
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
SkillId = 1,
|
||||||
|
Tier = SkillTier.I,
|
||||||
|
Effect = "MaxHealth",
|
||||||
|
Value = 25
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
SkillId = 1,
|
||||||
|
Tier = SkillTier.II,
|
||||||
|
Effect = "MaxHealth",
|
||||||
|
Value = 50
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 3,
|
||||||
|
SkillId = 1,
|
||||||
|
Tier = SkillTier.III,
|
||||||
|
Effect = "MaxHealth",
|
||||||
|
Value = 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Skill
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Name = "Mind Enhancement",
|
||||||
|
Description = "Increases maximum intelligence of your pet, improving its learning capabilities.",
|
||||||
|
Type = SkillType.GROUND,
|
||||||
|
PointsCost = 1,
|
||||||
|
Icon = "🧠",
|
||||||
|
SkillsIdRequired = null,
|
||||||
|
Effects = new List<SkillEffect>
|
||||||
|
{
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 4,
|
||||||
|
SkillId = 2,
|
||||||
|
Tier = SkillTier.I,
|
||||||
|
Effect = "MaxIntelligence",
|
||||||
|
Value = 5
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 5,
|
||||||
|
SkillId = 2,
|
||||||
|
Tier = SkillTier.II,
|
||||||
|
Effect = "MaxIntelligence",
|
||||||
|
Value = 10
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 6,
|
||||||
|
SkillId = 2,
|
||||||
|
Tier = SkillTier.III,
|
||||||
|
Effect = "MaxIntelligence",
|
||||||
|
Value = 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Skill
|
||||||
|
{
|
||||||
|
Id = 3,
|
||||||
|
Name = "Strength Training",
|
||||||
|
Description = "Increases maximum strength of your pet, making it more powerful.",
|
||||||
|
Type = SkillType.GROUND,
|
||||||
|
PointsCost = 1,
|
||||||
|
Icon = "💪",
|
||||||
|
SkillsIdRequired = null,
|
||||||
|
Effects = new List<SkillEffect>
|
||||||
|
{
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 7,
|
||||||
|
SkillId = 3,
|
||||||
|
Tier = SkillTier.I,
|
||||||
|
Effect = "MaxStrength",
|
||||||
|
Value = 5
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 8,
|
||||||
|
SkillId = 3,
|
||||||
|
Tier = SkillTier.II,
|
||||||
|
Effect = "MaxStrength",
|
||||||
|
Value = 10
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 9,
|
||||||
|
SkillId = 3,
|
||||||
|
Tier = SkillTier.III,
|
||||||
|
Effect = "MaxStrength",
|
||||||
|
Value = 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Skill
|
||||||
|
{
|
||||||
|
Id = 4,
|
||||||
|
Name = "Charisma Boost",
|
||||||
|
Description = "Increases maximum charisma of your pet, making it more charming.",
|
||||||
|
Type = SkillType.GROUND,
|
||||||
|
PointsCost = 1,
|
||||||
|
Icon = "🎭",
|
||||||
|
SkillsIdRequired = null,
|
||||||
|
Effects = new List<SkillEffect>
|
||||||
|
{
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 10,
|
||||||
|
SkillId = 4,
|
||||||
|
Tier = SkillTier.I,
|
||||||
|
Effect = "MaxCharisma",
|
||||||
|
Value = 5
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 11,
|
||||||
|
SkillId = 4,
|
||||||
|
Tier = SkillTier.II,
|
||||||
|
Effect = "MaxCharisma",
|
||||||
|
Value = 10
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 12,
|
||||||
|
SkillId = 4,
|
||||||
|
Tier = SkillTier.III,
|
||||||
|
Effect = "MaxCharisma",
|
||||||
|
Value = 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Skill
|
||||||
|
{
|
||||||
|
Id = 5,
|
||||||
|
Name = "Luck of the Draw",
|
||||||
|
Description = "Increases luck of your pet, making it more fortunate to find rare items.",
|
||||||
|
Type = SkillType.GROUND,
|
||||||
|
PointsCost = 1,
|
||||||
|
Icon = "🍀",
|
||||||
|
SkillsIdRequired = new List<int> { 4 },
|
||||||
|
Effects = new List<SkillEffect>
|
||||||
|
{
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 13,
|
||||||
|
SkillId = 5,
|
||||||
|
Tier = SkillTier.I,
|
||||||
|
Effect = "Luck",
|
||||||
|
Value = 1
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 14,
|
||||||
|
SkillId = 5,
|
||||||
|
Tier = SkillTier.II,
|
||||||
|
Effect = "Luck",
|
||||||
|
Value = 2
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 15,
|
||||||
|
SkillId = 5,
|
||||||
|
Tier = SkillTier.III,
|
||||||
|
Effect = "Luck",
|
||||||
|
Value = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Skill
|
||||||
|
{
|
||||||
|
Id = 6,
|
||||||
|
Name = "Agility Training",
|
||||||
|
Description = "Increases agility of your pet, making it faster in combat.",
|
||||||
|
Type = SkillType.GROUND,
|
||||||
|
PointsCost = 1,
|
||||||
|
Icon = "🏃",
|
||||||
|
SkillsIdRequired = new List<int> { 3 },
|
||||||
|
Effects = new List<SkillEffect>
|
||||||
|
{
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 16,
|
||||||
|
SkillId = 6,
|
||||||
|
Tier = SkillTier.I,
|
||||||
|
Effect = "Agility",
|
||||||
|
Value = 1
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 17,
|
||||||
|
SkillId = 6,
|
||||||
|
Tier = SkillTier.II,
|
||||||
|
Effect = "Agility",
|
||||||
|
Value = 2
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 18,
|
||||||
|
SkillId = 6,
|
||||||
|
Tier = SkillTier.III,
|
||||||
|
Effect = "Agility",
|
||||||
|
Value = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Skill
|
||||||
|
{
|
||||||
|
Id = 7,
|
||||||
|
Name = "Perception Boost",
|
||||||
|
Description = "Increases perception of your pet, making it more aware of its surroundings.",
|
||||||
|
Type = SkillType.GROUND,
|
||||||
|
PointsCost = 1,
|
||||||
|
Icon = "👀",
|
||||||
|
SkillsIdRequired = new List<int> { 2 },
|
||||||
|
Effects = new List<SkillEffect>
|
||||||
|
{
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 19,
|
||||||
|
SkillId = 7,
|
||||||
|
Tier = SkillTier.I,
|
||||||
|
Effect = "Perception",
|
||||||
|
Value = 1
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 20,
|
||||||
|
SkillId = 7,
|
||||||
|
Tier = SkillTier.II,
|
||||||
|
Effect = "Perception",
|
||||||
|
Value = 2
|
||||||
|
},
|
||||||
|
new SkillEffect
|
||||||
|
{
|
||||||
|
Id = 21,
|
||||||
|
SkillId = 7,
|
||||||
|
Tier = SkillTier.III,
|
||||||
|
Effect = "Perception",
|
||||||
|
Value = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
Items.csv
41
Items.csv
@ -1,20 +1,21 @@
|
|||||||
Item Name, Type, Rarity, Description
|
ItemId,Item Name, Type, Rarity, Description,Price,Effect
|
||||||
Basic Kibble,Consumable,Common,Adds +20 food resources
|
0,Apple,Material,Common,Crafting material (coming soon),0,Nothing
|
||||||
Superfood Smoothie,Consumable,Uncommon,Adds +30 food resources; Restores 5 Intelligence
|
1,Basic Kibble,Consumable,Common,Adds +20 food resources,0,ADD_FOOD_RESOURCES_20
|
||||||
Energy Drink,Consumable,Rare,Reduces Cooldown by 5 min
|
2,Superfood Smoothie,Consumable,Uncommon,Adds +30 food resources; Restores 5 Intelligence,0,ADD_FOOD_RESOURCES_30
|
||||||
Golden Apple,Consumable,Legendary,Adds +20 Intelligence (Permanent); Adds +100 food resources
|
3,Energy Drink,Consumable,Rare,Reduces Cooldown by 5 min,0,REDUCE_COOLDOWN_5
|
||||||
Healing Potion,Consumable,Uncommon,Adds +20 to Health; Adds +20 food resources
|
4,Golden Apple,Consumable,Legendary,Adds +20 Intelligence (Permanent); Adds +100 food resources,0,ADD_INTELLIGENCE_20
|
||||||
Charisma Cookie,Consumable,Rare,Adds +2 Charisma (Permanent)
|
5,Healing Potion,Consumable,Uncommon,Adds +20 to Health; Adds +20 food resources,0,ADD_HEALTH_20_AND_FOOD_20
|
||||||
XP Booster,Consumable,Rare,Award +10 XP
|
6,Charisma Cookie,Consumable,Rare,Adds +2 Charisma (Permanent),0,ADD_CHARISMA_2
|
||||||
Sleeping Draught,Consumable,Common,Reduces Cooldown for resting by 10 min
|
7,XP Booster,Consumable,Rare,Award +10 XP,0,ADD_XP_10
|
||||||
Mystery Meat,Consumable,Uncommon,Randomly ±2 to one stat (Permanent)
|
8,Sleeping Draught,Consumable,Common,Reduces Cooldown for resting by 10 min,0,REDUCE_REST_COOLDOWN_10
|
||||||
Elixir of Vitality,Consumable,Legendary,Fully restores all stats and health; Adds +1 Level
|
9,Mystery Meat,Consumable,Uncommon,Randomly ±2 to one stat (Permanent),0,ADD_RANDOM_STAT_2
|
||||||
Leather Hat,Equipment,Common,Helmet: +5 Max Health
|
10,Elixir of Vitality,Consumable,Legendary,Fully restores all stats and health; Adds +1 Level,0,RESTORE_STATS;ADD_LEVEL_1
|
||||||
Wizard Hat,Equipment,Rare,Helmet: +15 Max Intelligence
|
11,Leather Hat,Equipment,Common,Helmet: +5 Max Health,0,ADD_MAX_HEALTH_5
|
||||||
Knight's Armor,Equipment,Rare,Chest: +15 Max Strength
|
12,Wizard Hat,Equipment,Rare,Helmet: +15 Max Intelligence,0,ADD_MAX_INTELLIGENCE_15
|
||||||
Golden Boots,Equipment,Uncommon,Legging: +10 Max Charisma
|
13,Knight's Armor,Equipment,Rare,Chest: +15 Max Strength,0,ADD_MAX_STRENGTH_15
|
||||||
Laser Pointer,Equipment,Common,Weapon: +5 Max Strength
|
14,Golden Boots,Equipment,Uncommon,Legging: +10 Max Charisma,0,ADD_MAX_CHARISMA_10
|
||||||
Celestial Crown,Equipment,Legendary,Helmet: +20 max to all stats
|
15,Laser Pointer,Equipment,Common,Weapon: +5 Max Strength,0,ADD_MAX_STRENGTH_5
|
||||||
Dragon Scale Shield,Equipment,Legendary,Weapon: +50 Max Health
|
16,Celestial Crown,Equipment,Legendary,Helmet: +20 max to all stats,0,ADD_MAX_ALL_STATS_20
|
||||||
Feathers,Material,Common, Crafting material (coming soon)
|
17,Dragon Scale Shield,Equipment,Legendary,Weapon: +50 Max Health,0,ADD_MAX_HEALTH_50
|
||||||
Phoenix Feather,Material,Legendary, Crafting material (coming soon)
|
18,Feathers,Material,Common,Crafting material (coming soon),0,Nothing
|
||||||
|
19,Phoenix Feather,Material,Legendary,Crafting material (coming soon),0,Nothing
|
|
141
Migrations/20250201173643_Initial.Designer.cs
generated
141
Migrations/20250201173643_Initial.Designer.cs
generated
@ -1,141 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using PetCompanion.Data;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace PetCompanion.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(ApplicationDbContext))]
|
|
||||||
[Migration("20250201173643_Initial")]
|
|
||||||
partial class Initial
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.1");
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.Pet", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("Id")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<DateTime>("BasicActionCooldown")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("Class")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<DateTime>("GatherActionSince")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDead")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Level")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("PetBasicAction")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("PetGatherAction")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("UserId")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.ToTable("Pets");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.PetStats", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("PetId")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("Charisma")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Intelligence")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("MaxCharisma")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("MaxIntelligence")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("MaxStrength")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Strength")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.HasKey("PetId");
|
|
||||||
|
|
||||||
b.ToTable("PetStats");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.Resources", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("PetId")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("Food")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Gold")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Junk")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Wisdom")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.HasKey("PetId");
|
|
||||||
|
|
||||||
b.ToTable("Resources");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.PetStats", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("PetCompanion.Models.Pet", null)
|
|
||||||
.WithOne("Stats")
|
|
||||||
.HasForeignKey("PetCompanion.Models.PetStats", "PetId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.Resources", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("PetCompanion.Models.Pet", null)
|
|
||||||
.WithOne("Resources")
|
|
||||||
.HasForeignKey("PetCompanion.Models.Resources", "PetId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.Pet", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Resources")
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Stats")
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace PetCompanion.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class Initial : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Pets",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<string>(type: "TEXT", nullable: false),
|
|
||||||
Name = table.Column<string>(type: "TEXT", nullable: false),
|
|
||||||
Class = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
Level = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
UserId = table.Column<string>(type: "TEXT", nullable: false),
|
|
||||||
IsDead = table.Column<bool>(type: "INTEGER", nullable: false),
|
|
||||||
PetGatherAction = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
GatherActionSince = table.Column<DateTime>(type: "TEXT", nullable: false),
|
|
||||||
PetBasicAction = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
BasicActionCooldown = table.Column<DateTime>(type: "TEXT", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Pets", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "PetStats",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
PetId = table.Column<string>(type: "TEXT", nullable: false),
|
|
||||||
Intelligence = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
Strength = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
Charisma = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
MaxIntelligence = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
MaxStrength = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
MaxCharisma = table.Column<int>(type: "INTEGER", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_PetStats", x => x.PetId);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_PetStats_Pets_PetId",
|
|
||||||
column: x => x.PetId,
|
|
||||||
principalTable: "Pets",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Resources",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
PetId = table.Column<string>(type: "TEXT", nullable: false),
|
|
||||||
Wisdom = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
Gold = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
Food = table.Column<int>(type: "INTEGER", nullable: false),
|
|
||||||
Junk = table.Column<int>(type: "INTEGER", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Resources", x => x.PetId);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Resources_Pets_PetId",
|
|
||||||
column: x => x.PetId,
|
|
||||||
principalTable: "Pets",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "PetStats");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Resources");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Pets");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,138 +0,0 @@
|
|||||||
// <auto-generated />
|
|
||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|
||||||
using PetCompanion.Data;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace PetCompanion.Migrations
|
|
||||||
{
|
|
||||||
[DbContext(typeof(ApplicationDbContext))]
|
|
||||||
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
|
|
||||||
{
|
|
||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
|
||||||
{
|
|
||||||
#pragma warning disable 612, 618
|
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "9.0.1");
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.Pet", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("Id")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<DateTime>("BasicActionCooldown")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("Class")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<DateTime>("GatherActionSince")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDead")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Level")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("PetBasicAction")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("PetGatherAction")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<string>("UserId")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.ToTable("Pets");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.PetStats", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("PetId")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("Charisma")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Intelligence")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("MaxCharisma")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("MaxIntelligence")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("MaxStrength")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Strength")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.HasKey("PetId");
|
|
||||||
|
|
||||||
b.ToTable("PetStats");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.Resources", b =>
|
|
||||||
{
|
|
||||||
b.Property<string>("PetId")
|
|
||||||
.HasColumnType("TEXT");
|
|
||||||
|
|
||||||
b.Property<int>("Food")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Gold")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Junk")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.Property<int>("Wisdom")
|
|
||||||
.HasColumnType("INTEGER");
|
|
||||||
|
|
||||||
b.HasKey("PetId");
|
|
||||||
|
|
||||||
b.ToTable("Resources");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.PetStats", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("PetCompanion.Models.Pet", null)
|
|
||||||
.WithOne("Stats")
|
|
||||||
.HasForeignKey("PetCompanion.Models.PetStats", "PetId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.Resources", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("PetCompanion.Models.Pet", null)
|
|
||||||
.WithOne("Resources")
|
|
||||||
.HasForeignKey("PetCompanion.Models.Resources", "PetId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("PetCompanion.Models.Pet", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Resources")
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Stats")
|
|
||||||
.IsRequired();
|
|
||||||
});
|
|
||||||
#pragma warning restore 612, 618
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
namespace PetCompanion.Models.Enums
|
|
||||||
{
|
|
||||||
public enum ItemType
|
|
||||||
{
|
|
||||||
Consumable,
|
|
||||||
Equipment,
|
|
||||||
Material
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ItemRarity
|
|
||||||
{
|
|
||||||
Common,
|
|
||||||
Uncommon,
|
|
||||||
Rare,
|
|
||||||
Legendary
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum EquipmentSlot
|
|
||||||
{
|
|
||||||
Helmet,
|
|
||||||
Chest,
|
|
||||||
Leggings,
|
|
||||||
Weapon
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
using PetCompanion.Models.Enums;
|
|
||||||
|
|
||||||
namespace PetCompanion.Models
|
|
||||||
{
|
|
||||||
public class MaterialItem : Item
|
|
||||||
{
|
|
||||||
public MaterialItem()
|
|
||||||
{
|
|
||||||
Type = ItemType.Material;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Use(ref Pet pet)
|
|
||||||
{
|
|
||||||
// Materials cannot be used directly
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class StatBoostEquipment : EquipableItem
|
|
||||||
{
|
|
||||||
public Dictionary<string, int> StatBoosts { get; set; } = new();
|
|
||||||
|
|
||||||
public override void Equip(ref Pet pet)
|
|
||||||
{
|
|
||||||
base.Equip(ref pet);
|
|
||||||
if (IsEquipped)
|
|
||||||
{
|
|
||||||
foreach (var boost in StatBoosts)
|
|
||||||
{
|
|
||||||
switch (boost.Key.ToLower())
|
|
||||||
{
|
|
||||||
case "health":
|
|
||||||
pet.MaxHealth += boost.Value;
|
|
||||||
break;
|
|
||||||
case "intelligence":
|
|
||||||
pet.Stats.MaxIntelligence += boost.Value;
|
|
||||||
break;
|
|
||||||
case "strength":
|
|
||||||
pet.Stats.MaxStrength += boost.Value;
|
|
||||||
break;
|
|
||||||
case "charisma":
|
|
||||||
pet.Stats.MaxCharisma += boost.Value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Unequip(ref Pet pet)
|
|
||||||
{
|
|
||||||
if (IsEquipped)
|
|
||||||
{
|
|
||||||
foreach (var boost in StatBoosts)
|
|
||||||
{
|
|
||||||
switch (boost.Key.ToLower())
|
|
||||||
{
|
|
||||||
case "health":
|
|
||||||
pet.MaxHealth -= boost.Value;
|
|
||||||
break;
|
|
||||||
case "intelligence":
|
|
||||||
pet.Stats.MaxIntelligence -= boost.Value;
|
|
||||||
break;
|
|
||||||
case "strength":
|
|
||||||
pet.Stats.MaxStrength -= boost.Value;
|
|
||||||
break;
|
|
||||||
case "charisma":
|
|
||||||
pet.Stats.MaxCharisma -= boost.Value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base.Unequip(ref pet);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Use(ref Pet pet)
|
|
||||||
{
|
|
||||||
Equip(ref pet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
namespace PetCompanion.Models
|
|
||||||
{
|
|
||||||
public class Inventory
|
|
||||||
{
|
|
||||||
public List<Item> Items { get; set; } = new();
|
|
||||||
public int Capacity { get; set; }
|
|
||||||
|
|
||||||
public bool AddItem(Item item)
|
|
||||||
{
|
|
||||||
if (Items.Count < Capacity)
|
|
||||||
{
|
|
||||||
Items.Add(item);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool RemoveItem(Item item)
|
|
||||||
{
|
|
||||||
return Items.Remove(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void TrashItem(Item item)
|
|
||||||
{
|
|
||||||
RemoveItem(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
using PetCompanion.Models.Enums;
|
|
||||||
|
|
||||||
namespace PetCompanion.Models
|
|
||||||
{
|
|
||||||
public abstract class Item
|
|
||||||
{
|
|
||||||
public string Id { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public ItemType Type { get; set; }
|
|
||||||
public ItemRarity Rarity { get; set; }
|
|
||||||
|
|
||||||
public abstract void Use(ref Pet pet);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class EquipableItem : Item
|
|
||||||
{
|
|
||||||
public EquipmentSlot Slot { get; set; }
|
|
||||||
public bool IsEquipped { get; set; }
|
|
||||||
|
|
||||||
public virtual void Equip(ref Pet pet)
|
|
||||||
{
|
|
||||||
if (!IsEquipped)
|
|
||||||
{
|
|
||||||
pet.Equipment[Slot]?.Unequip(ref pet);
|
|
||||||
pet.Equipment[Slot] = this;
|
|
||||||
IsEquipped = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void Unequip(ref Pet pet)
|
|
||||||
{
|
|
||||||
if (IsEquipped)
|
|
||||||
{
|
|
||||||
pet.Equipment[Slot] = null;
|
|
||||||
IsEquipped = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ConsumableItem : Item
|
|
||||||
{
|
|
||||||
public Action<Pet> Effect { get; set; }
|
|
||||||
|
|
||||||
public override void Use(ref Pet pet)
|
|
||||||
{
|
|
||||||
Effect?.Invoke(pet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,6 +27,9 @@ namespace PetCompanion.Models
|
|||||||
|
|
||||||
public Dictionary<EquipmentSlot, EquipableItem> Equipment { get; set; } = new();
|
public Dictionary<EquipmentSlot, EquipableItem> Equipment { get; set; } = new();
|
||||||
|
|
||||||
|
public int SkillPoints { get; set; } = 2;
|
||||||
|
public virtual ICollection<PetSkill> Skills { get; set; } = new List<PetSkill>();
|
||||||
|
|
||||||
public Pet()
|
public Pet()
|
||||||
{
|
{
|
||||||
foreach (EquipmentSlot slot in Enum.GetValues(typeof(EquipmentSlot)))
|
foreach (EquipmentSlot slot in Enum.GetValues(typeof(EquipmentSlot)))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace PetCompanion.Models
|
namespace PetCompanion.Models
|
||||||
{
|
{
|
||||||
@ -7,10 +8,20 @@ namespace PetCompanion.Models
|
|||||||
{
|
{
|
||||||
[Key, ForeignKey("Pet")]
|
[Key, ForeignKey("Pet")]
|
||||||
public string PetId { get; set; }
|
public string PetId { get; set; }
|
||||||
|
|
||||||
|
// Display stats
|
||||||
public int Intelligence { get; set; }
|
public int Intelligence { get; set; }
|
||||||
public int Strength { get; set; }
|
public int Strength { get; set; }
|
||||||
public int Charisma { get; set; }
|
public int Charisma { get; set; }
|
||||||
|
|
||||||
|
// Hidden stats (not displayed to the API)
|
||||||
|
[JsonIgnore]
|
||||||
|
public int Luck { get; set; } // used for rarity of item finds
|
||||||
|
[JsonIgnore]
|
||||||
|
public int Agility { get; set; } // used for combat
|
||||||
|
[JsonIgnore]
|
||||||
|
public int Perception { get; set; } // used for number of itens found
|
||||||
|
|
||||||
public int MaxIntelligence { get; set; }
|
public int MaxIntelligence { get; set; }
|
||||||
public int MaxStrength { get; set; }
|
public int MaxStrength { get; set; }
|
||||||
public int MaxCharisma { get; set; }
|
public int MaxCharisma { get; set; }
|
||||||
@ -67,6 +78,10 @@ namespace PetCompanion.Models
|
|||||||
stats.MaxStrength = stats.Strength;
|
stats.MaxStrength = stats.Strength;
|
||||||
stats.MaxCharisma = stats.Charisma;
|
stats.MaxCharisma = stats.Charisma;
|
||||||
|
|
||||||
|
stats.Luck = 1;
|
||||||
|
stats.Agility = 1;
|
||||||
|
stats.Perception = 1;
|
||||||
|
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
82
Models/Skill.cs
Normal file
82
Models/Skill.cs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace PetCompanion.Models
|
||||||
|
{
|
||||||
|
public enum SkillType
|
||||||
|
{
|
||||||
|
GROUND,
|
||||||
|
GRAND
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SkillTier
|
||||||
|
{
|
||||||
|
I = 1,
|
||||||
|
II = 2,
|
||||||
|
III = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Skill
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public SkillType Type { get; set; }
|
||||||
|
public int PointsCost { get; set; }
|
||||||
|
public string Icon { get; set; }
|
||||||
|
public List<int>? SkillsIdRequired { get; set; }
|
||||||
|
public virtual ICollection<SkillEffect> Effects { get; set; }
|
||||||
|
public virtual ICollection<PetSkill> PetSkills { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SkillEffect
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int SkillId { get; set; }
|
||||||
|
public virtual Skill Skill { get; set; }
|
||||||
|
public SkillTier Tier { get; set; }
|
||||||
|
public string Effect { get; set; }
|
||||||
|
public decimal Value { get; set; }
|
||||||
|
|
||||||
|
public void PetSkillUpgrade(ref Pet pet)
|
||||||
|
{
|
||||||
|
switch (Effect)
|
||||||
|
{
|
||||||
|
case "MaxHealth":
|
||||||
|
pet.MaxHealth += (int)Value;
|
||||||
|
break;
|
||||||
|
case "MaxIntelligence":
|
||||||
|
pet.Stats.MaxIntelligence += (int)Value;
|
||||||
|
break;
|
||||||
|
case "MaxStrength":
|
||||||
|
pet.Stats.MaxStrength += (int)Value;
|
||||||
|
break;
|
||||||
|
case "MaxCharisma":
|
||||||
|
pet.Stats.MaxCharisma += (int)Value;
|
||||||
|
break;
|
||||||
|
case "Luck":
|
||||||
|
pet.Stats.Luck += (int)Value;
|
||||||
|
break;
|
||||||
|
case "Agility":
|
||||||
|
pet.Stats.Agility += (int)Value;
|
||||||
|
break;
|
||||||
|
case "Perception":
|
||||||
|
pet.Stats.Perception += (int)Value;
|
||||||
|
break;
|
||||||
|
// Add more effects as needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PetSkill
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string PetId { get; set; }
|
||||||
|
public virtual Pet Pet { get; set; }
|
||||||
|
public int SkillId { get; set; }
|
||||||
|
public virtual Skill Skill { get; set; }
|
||||||
|
public SkillTier CurrentTier { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,7 @@ namespace PetCompanion
|
|||||||
|
|
||||||
builder.Services.AddScoped<PetClassRepository>();
|
builder.Services.AddScoped<PetClassRepository>();
|
||||||
builder.Services.AddScoped<PetClassService>();
|
builder.Services.AddScoped<PetClassService>();
|
||||||
|
builder.Services.AddScoped<SkillService>();
|
||||||
builder.Services.AddScoped<PetRepository>();
|
builder.Services.AddScoped<PetRepository>();
|
||||||
builder.Services.AddScoped<PetService>();
|
builder.Services.AddScoped<PetService>();
|
||||||
|
|
||||||
|
@ -1,176 +0,0 @@
|
|||||||
using System.Text.RegularExpressions;
|
|
||||||
using PetCompanion.Models;
|
|
||||||
using PetCompanion.Models.Enums;
|
|
||||||
|
|
||||||
namespace PetCompanion.Repositories
|
|
||||||
{
|
|
||||||
public class ItemRepository
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, Item> _itemTemplates = new();
|
|
||||||
private readonly Dictionary<ItemRarity, List<string>> _itemsByRarity = new();
|
|
||||||
private readonly Random _random = new();
|
|
||||||
|
|
||||||
public ItemRepository()
|
|
||||||
{
|
|
||||||
foreach (ItemRarity rarity in Enum.GetValues(typeof(ItemRarity)))
|
|
||||||
{
|
|
||||||
_itemsByRarity[rarity] = new List<string>();
|
|
||||||
}
|
|
||||||
LoadItemsFromCsv();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadItemsFromCsv()
|
|
||||||
{
|
|
||||||
var lines = File.ReadAllLines("Items.csv").Skip(1); // Skip header
|
|
||||||
foreach (var line in lines)
|
|
||||||
{
|
|
||||||
var parts = line.Split(',');
|
|
||||||
var name = parts[0];
|
|
||||||
var type = Enum.Parse<ItemType>(parts[1]);
|
|
||||||
var rarity = Enum.Parse<ItemRarity>(parts[2]);
|
|
||||||
var description = parts[3];
|
|
||||||
|
|
||||||
Item item = type switch
|
|
||||||
{
|
|
||||||
ItemType.Consumable => CreateConsumableItem(name, description, rarity),
|
|
||||||
ItemType.Equipment => CreateEquipmentItem(name, description, rarity),
|
|
||||||
ItemType.Material => CreateMaterialItem(name, description, rarity),
|
|
||||||
_ => throw new ArgumentException($"Unknown item type: {type}")
|
|
||||||
};
|
|
||||||
|
|
||||||
_itemTemplates.Add(name, item);
|
|
||||||
_itemsByRarity[rarity].Add(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Item CreateConsumableItem(string name, string description, ItemRarity rarity)
|
|
||||||
{
|
|
||||||
var item = new ConsumableItem
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid().ToString(),
|
|
||||||
Name = name,
|
|
||||||
Description = description,
|
|
||||||
Type = ItemType.Consumable,
|
|
||||||
Rarity = rarity
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse effects from description
|
|
||||||
if (description.Contains("food resources"))
|
|
||||||
{
|
|
||||||
var foodAmount = int.Parse(Regex.Match(description, @"\+(\d+) food").Groups[1].Value);
|
|
||||||
item.Effect = (pet) => pet.Resources.Food += foodAmount;
|
|
||||||
}
|
|
||||||
else if (description.Contains("Intelligence"))
|
|
||||||
{
|
|
||||||
var amount = int.Parse(Regex.Match(description, @"\+(\d+)").Groups[1].Value);
|
|
||||||
item.Effect = (pet) => pet.IncrementIntelligence(amount);
|
|
||||||
}
|
|
||||||
// Add more effect parsing as needed
|
|
||||||
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Item CreateEquipmentItem(string name, string description, ItemRarity rarity)
|
|
||||||
{
|
|
||||||
var equipment = new StatBoostEquipment
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid().ToString(),
|
|
||||||
Name = name,
|
|
||||||
Description = description,
|
|
||||||
Type = ItemType.Equipment,
|
|
||||||
Rarity = rarity
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse slot and stats from description
|
|
||||||
var slotMatch = Regex.Match(description, @"(Helmet|Chest|Legging|Weapon):");
|
|
||||||
if (slotMatch.Success)
|
|
||||||
{
|
|
||||||
equipment.Slot = Enum.Parse<EquipmentSlot>(slotMatch.Groups[1].Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
var statMatch = Regex.Match(description, @"\+(\d+) Max (\w+)");
|
|
||||||
if (statMatch.Success)
|
|
||||||
{
|
|
||||||
var amount = int.Parse(statMatch.Groups[1].Value);
|
|
||||||
var stat = statMatch.Groups[2].Value;
|
|
||||||
equipment.StatBoosts.Add(stat, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
return equipment;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Item CreateMaterialItem(string name, string description, ItemRarity rarity)
|
|
||||||
{
|
|
||||||
return new MaterialItem
|
|
||||||
{
|
|
||||||
Id = Guid.NewGuid().ToString(),
|
|
||||||
Name = name,
|
|
||||||
Description = description,
|
|
||||||
Type = ItemType.Material,
|
|
||||||
Rarity = rarity
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public Item CreateItem(string itemName)
|
|
||||||
{
|
|
||||||
if (_itemTemplates.TryGetValue(itemName, out var template))
|
|
||||||
{
|
|
||||||
// Create a new instance with a new ID but same properties
|
|
||||||
var json = System.Text.Json.JsonSerializer.Serialize(template);
|
|
||||||
var newItem = System.Text.Json.JsonSerializer.Deserialize<Item>(json);
|
|
||||||
newItem.Id = Guid.NewGuid().ToString();
|
|
||||||
return newItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new KeyNotFoundException($"Item template not found: {itemName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Usage:
|
|
||||||
/* var rarityProbabilities = new Dictionary<ItemRarity, int>
|
|
||||||
{
|
|
||||||
{ ItemRarity.Common, 50 }, // 50% chance
|
|
||||||
{ ItemRarity.Uncommon, 30 }, // 30% chance
|
|
||||||
{ ItemRarity.Rare, 15 }, // 15% chance
|
|
||||||
{ ItemRarity.Legendary, 5 } // 5% chance
|
|
||||||
};
|
|
||||||
|
|
||||||
var itemRepo = new ItemRepository();
|
|
||||||
var randomItem = itemRepo.GenerateRandomItem(rarityProbabilities);
|
|
||||||
*/
|
|
||||||
public Item GenerateRandomItem(Dictionary<ItemRarity, int> rarityProbabilities)
|
|
||||||
{
|
|
||||||
// Validate probabilities
|
|
||||||
if (rarityProbabilities.Values.Sum() != 100)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Rarity probabilities must sum to 100");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate random number between 0 and 100
|
|
||||||
var roll = _random.Next(1, 101);
|
|
||||||
var currentThreshold = 0;
|
|
||||||
|
|
||||||
// Determine which rarity we hit
|
|
||||||
ItemRarity selectedRarity = ItemRarity.Common;
|
|
||||||
foreach (var probability in rarityProbabilities)
|
|
||||||
{
|
|
||||||
currentThreshold += probability.Value;
|
|
||||||
if (roll <= currentThreshold)
|
|
||||||
{
|
|
||||||
selectedRarity = probability.Key;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get random item from selected rarity
|
|
||||||
var possibleItems = _itemsByRarity[selectedRarity];
|
|
||||||
if (possibleItems.Count == 0)
|
|
||||||
{
|
|
||||||
// Fallback to common if no items of selected rarity
|
|
||||||
possibleItems = _itemsByRarity[ItemRarity.Common];
|
|
||||||
}
|
|
||||||
|
|
||||||
var randomItemName = possibleItems[_random.Next(possibleItems.Count)];
|
|
||||||
return CreateItem(randomItemName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
76
Services/SkillService.cs
Normal file
76
Services/SkillService.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
using PetCompanion.Models;
|
||||||
|
using PetCompanion.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using PetCompanion.Repositories;
|
||||||
|
|
||||||
|
namespace PetCompanion.Services
|
||||||
|
{
|
||||||
|
public class SkillService
|
||||||
|
{
|
||||||
|
private readonly ApplicationDbContext context;
|
||||||
|
private readonly PetRepository petRepository;
|
||||||
|
|
||||||
|
public SkillService(ApplicationDbContext context, PetRepository petRepository)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.petRepository = petRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PetSkill> AllocateSkillPoint(string petId, string userId, int skillId)
|
||||||
|
{
|
||||||
|
var pet = await context.Pets
|
||||||
|
.Include(p => p.Skills)
|
||||||
|
.FirstOrDefaultAsync(p => p.Id == petId && p.UserId == userId);
|
||||||
|
|
||||||
|
if (pet == null)
|
||||||
|
throw new Exception("Pet not found");
|
||||||
|
|
||||||
|
if (pet.SkillPoints <= 0)
|
||||||
|
throw new Exception("No skill points available");
|
||||||
|
|
||||||
|
var skill = await context.Skills
|
||||||
|
.Include(s => s.Effects)
|
||||||
|
.FirstOrDefaultAsync(s => s.Id == skillId);
|
||||||
|
|
||||||
|
if (skill == null)
|
||||||
|
throw new Exception("Skill not found");
|
||||||
|
|
||||||
|
var existingSkill = pet.Skills.FirstOrDefault(ps => ps.SkillId == skillId);
|
||||||
|
if (existingSkill != null)
|
||||||
|
{
|
||||||
|
if (existingSkill.CurrentTier == SkillTier.III)
|
||||||
|
throw new Exception("Skill already at maximum tier");
|
||||||
|
|
||||||
|
existingSkill.CurrentTier++;
|
||||||
|
var effect = skill.Effects.FirstOrDefault(e => e.Tier == existingSkill.CurrentTier);
|
||||||
|
if (effect != null)
|
||||||
|
effect.PetSkillUpgrade(ref pet);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var newSkill = new PetSkill
|
||||||
|
{
|
||||||
|
PetId = petId,
|
||||||
|
SkillId = skillId,
|
||||||
|
CurrentTier = SkillTier.I
|
||||||
|
};
|
||||||
|
pet.Skills.Add(newSkill);
|
||||||
|
var effect = skill.Effects.FirstOrDefault(e => e.Tier == SkillTier.I);
|
||||||
|
if (effect != null)
|
||||||
|
effect.PetSkillUpgrade(ref pet);
|
||||||
|
}
|
||||||
|
|
||||||
|
pet.SkillPoints--;
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
|
||||||
|
return pet.Skills.First(ps => ps.SkillId == skillId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Skill>> GetAvailableSkills()
|
||||||
|
{
|
||||||
|
return await context.Skills
|
||||||
|
.Include(s => s.Effects)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user