This commit is contained in:
MuHua-123
2025-07-25 17:46:56 +08:00
parent 36c827fd24
commit b6adf24ff1
21 changed files with 326 additions and 184 deletions
@@ -1,46 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 战斗角色
/// </summary>
public class BattleCharacter : DataAttribute {
/// <summary> 角色数据 </summary>
public readonly DataCharacter character;
/// <summary> 归属队伍 </summary>
public int team;
/// <summary> 角色名字 </summary>
public string name;
/// <summary> 战斗等级 </summary>
public int level;
/// <summary> 战场位置 </summary>
public int position;
/// <summary> 先攻顺序 </summary>
public int sequence;
/// <summary> 护甲等级 </summary>
public int armorClass;
/// <summary> 生命点 </summary>
public Vector2Int hitPoint;
public BattleCharacter(DataCharacter character, int team) {
this.character = character;
AttributeTool.Cover(this, character);
this.team = team;
name = character.name;
level = character.Level;
position = 1;
hitPoint = new Vector2Int(character.HitPoint, character.HitPoint);
armorClass = character.ArmorClass;
}
/// <summary> 是否允许行动 </summary>
public bool IsAction() {
return hitPoint.x > 0;
}
/// <summary> 是否敌对目标 </summary>
public bool IsHostility(BattleCharacter target) {
return team != target.team && target.hitPoint.x > 0;
}
}
@@ -6,22 +6,15 @@ using UnityEngine;
/// 阶段类型
/// </summary>
public enum PhaseType {
,
,
,
,
,
, , , , ,
,
}
/// <summary>
/// 阶段
/// </summary>
public interface IPhase {
/// <summary> 开始阶段 </summary>
public void StartPhase();
/// <summary> 更新阶段 </summary>
public void UpdatePhase();
/// <summary> 退出阶段 </summary>
public void QuitPhase();
/// <summary> 执行阶段 </summary>
public void Execute();
}
/// <summary>
/// 战斗阶段
@@ -30,12 +23,12 @@ public abstract class BattlePhase : IPhase {
/// <summary> 模拟器 </summary>
public readonly BattleSimulator simulator;
/// <summary> 行动角色 </summary>
public DataCombatRole ActionRole => simulator.actionRole;
/// <summary> 战斗队列 </summary>
public BattleQueue BattleQueue => simulator.battleQueue;
public BattlePhase(BattleSimulator simulator) => this.simulator = simulator;
public abstract void StartPhase();
public abstract void UpdatePhase();
public abstract void QuitPhase();
public abstract void Execute();
}
@@ -6,55 +6,70 @@ using UnityEngine;
/// 行动阶段
/// </summary>
public class PhaseAction : BattlePhase {
/// <summary> 当前行动 </summary>
private BattleCharacter currentAction;
/// <summary> 当前目标 </summary>
private BattleCharacter currentTarget;
public PhaseAction(BattleSimulator simulator) : base(simulator) { }
public override void StartPhase() {
// throw new System.NotImplementedException();
}
public override void UpdatePhase() {
// 选择行动的角色,如果没有则进入下一轮
if (!SelectAction()) { return; }
// 选择攻击的目标,如果没有目标则结算战斗
if (!SelectTarget()) { return; }
// 命中检定
int hit = Dice.Roll20(currentAction.DexModifier);
int ac = currentTarget.armorClass;
bool isHit = hit > ac;
// 伤害计算
if (isHit) {
int damage = Dice.Roll8(currentAction.StrModifier);
currentTarget.hitPoint.x -= damage;
Debug.Log($"{currentAction.name}使用 普通攻击({hit}) 对 {currentTarget.name}({ac}) 造成 {damage} 点伤害!");
}
else {
Debug.Log($"{currentAction.name}使用 普通攻击({hit}) 对 {currentTarget.name}({ac}) 未命中!");
}
// TODO:记录器
// Debug.Log($"正式回合:{roundCount}");
}
public override void QuitPhase() {
// throw new System.NotImplementedException();
}
public override void Execute() {
/// <summary> 选择当前行动角色 </summary>
private bool SelectAction() {
// 选择行动的角色,如果没有则进入下一回合
if (!BattleQueue.Dequeue(out currentAction)) { simulator.Transition(PhaseType.); return false; }
// 判断是否可以行动
if (!currentAction.IsAction()) { return false; }
return true;
}
/// <summary> 选择当前目标角色 </summary>
private bool SelectTarget() {
// 选择一个可以攻击的目标
currentTarget = BattleQueue.FirstOrDefault(obj => currentAction.IsHostility(obj));
// 如果没有可以攻击的目标则结算战斗
if (currentTarget == null) { simulator.Transition(PhaseType.); }
return currentTarget != null;
}
}
/// <summary>
/// 行动角色选择
/// </summary>
public class PhaseActionRoleSelect : BattlePhase {
public PhaseActionRoleSelect(BattleSimulator simulator) : base(simulator) { }
public override void Execute() {
// 选择行动的角色,如果没有则进入下一回合
PhaseType phase = BattleQueue.Dequeue(out simulator.actionRole) ? PhaseType. : PhaseType.;
simulator.Transition(phase);
}
}
/// <summary>
/// 行动角色攻击
/// </summary>
public class PhaseActionRoleAttack : BattlePhase {
public PhaseActionRoleAttack(BattleSimulator simulator) : base(simulator) { }
public override void Execute() {
// 判断是否可以行动
if (ActionRole.hitPoint.x <= 0) { simulator.Transition(PhaseType.); return; }
// 选择可以攻击的目标
List<DataCombatRole> roles = AttackTarget();
// 如果没有可以攻击的目标则结算战斗
if (roles.Count == 0) { simulator.Transition(PhaseType.); return; }
// 攻击单体目标
int randomIndex = Random.Range(0, roles.Count);
DataCombatRole target = roles[randomIndex];
// 武器判断
// ActionRole.weapon1
// 命中检定
int hit = Dice.Roll20(ActionRole.StrModifier);
int armorClass = target.armorClass;
// 伤害计算
int damage = Dice.Roll8(ActionRole.StrModifier);
if (hit > armorClass) { target.hitPoint.x -= damage; }
// 生成战斗消息
MessageNormalAttack message = new MessageNormalAttack();
message.Settings(ActionRole, hit, damage);
message.Settings(target, armorClass);
Debug.Log(message);
simulator.Transition(PhaseType.);
}
/// <summary> 攻击目标 </summary>
private List<DataCombatRole> AttackTarget() {
return BattleQueue.Where(Hostility);
}
/// <summary> 敌对目标 </summary>
public bool Hostility(DataCombatRole role) {
return role.team != ActionRole.team && role.hitPoint.x > 0;
}
}
/// <summary>
/// 战斗行动
/// </summary>
public class BattleAction {
}
@@ -9,13 +9,7 @@ public class PhaseAssault : BattlePhase {
public PhaseAssault(BattleSimulator simulator) : base(simulator) { }
public override void StartPhase() {
// throw new System.NotImplementedException();
}
public override void UpdatePhase() {
// throw new System.NotImplementedException();
}
public override void QuitPhase() {
// throw new System.NotImplementedException();
public override void Execute() {
}
}
@@ -9,17 +9,10 @@ public class PhaseFinish : BattlePhase {
public PhaseFinish(BattleSimulator simulator) : base(simulator) { }
public override void StartPhase() {
// TODO:记录器
Debug.Log("结束战斗!");
}
public override void UpdatePhase() {
public override void Execute() {
// TODO:需要添加结算判断
// simulator.Transition(PhaseType.回合阶段);
// TODO:记录器
}
public override void QuitPhase() {
// throw new System.NotImplementedException();
Debug.Log("结束战斗!");
}
}
@@ -11,20 +11,14 @@ public class PhaseFormal : BattlePhase {
public PhaseFormal(BattleSimulator simulator) : base(simulator) { }
public override void StartPhase() {
// throw new System.NotImplementedException();
}
public override void UpdatePhase() {
public override void Execute() {
roundCount++;
BattleQueue.UpdateQueue();
simulator.Transition(PhaseType.);
// TODO:记录器
Debug.Log($"正式回合:{roundCount}");
string message = "存活";
BattleQueue.ForEach(obj => message += $" {obj.name}({obj.hitPoint.x})");
Debug.Log(message);
}
public override void QuitPhase() {
// throw new System.NotImplementedException();
simulator.Transition(PhaseType.);
}
}
@@ -9,20 +9,14 @@ public class PhaseInitiative : BattlePhase {
public PhaseInitiative(BattleSimulator simulator) : base(simulator) { }
public override void StartPhase() {
// throw new System.NotImplementedException();
}
public override void UpdatePhase() {
public override void Execute() {
BattleQueue.ForEach(obj => obj.sequence = Dice.Roll20(obj.DexModifier));
BattleQueue.OrderByDescending(c => c.sequence);
// TODO:需要添加突袭阶段
simulator.Transition(PhaseType.);
// TODO:记录器
string message = "先攻";
BattleQueue.ForEach(obj => message += $" {obj.name}({obj.sequence})");
Debug.Log(message);
}
public override void QuitPhase() {
// throw new System.NotImplementedException();
simulator.Transition(PhaseType.);
}
}
+10 -10
View File
@@ -9,40 +9,40 @@ using UnityEngine;
/// </summary>
public class BattleQueue {
/// <summary> 执行队列 </summary>
public Queue<BattleCharacter> queue = new Queue<BattleCharacter>();
public Queue<DataCombatRole> queue = new Queue<DataCombatRole>();
/// <summary> 战斗合集 </summary>
public List<BattleCharacter> characters = new List<BattleCharacter>();
public List<DataCombatRole> characters = new List<DataCombatRole>();
/// <summary> 添加角色 </summary>
public void Add(List<BattleCharacter> list) {
public void Add(List<DataCombatRole> list) {
characters.AddRange(list);
}
/// <summary> 添加角色 </summary>
public void Add(BattleCharacter character) {
public void Add(DataCombatRole character) {
characters.Add(character);
}
/// <summary> 遍历角色 </summary>
public void ForEach(Action<BattleCharacter> action) {
public void ForEach(Action<DataCombatRole> action) {
characters.ForEach(action);
}
// /// <summary> 排序:大到小 </summary>
public void OrderByDescending(Func<BattleCharacter, int> func) {
public void OrderByDescending(Func<DataCombatRole, int> func) {
characters = characters.OrderByDescending(func).ToList();
}
/// <summary> 根据条件查询元素 </summary>
public List<BattleCharacter> Where(Func<BattleCharacter, bool> predicate) {
public List<DataCombatRole> Where(Func<DataCombatRole, bool> predicate) {
return characters.Where(predicate).ToList();
}
/// <summary> 根据条件查询第一个匹配的元素 </summary>
public BattleCharacter FirstOrDefault(Func<BattleCharacter, bool> predicate) {
public DataCombatRole FirstOrDefault(Func<DataCombatRole, bool> predicate) {
return characters.FirstOrDefault(predicate);
}
/// <summary> 更新队列 </summary>
public void UpdateQueue() {
queue = new Queue<BattleCharacter>(characters);
queue = new Queue<DataCombatRole>(characters);
}
/// <summary> 取出一个 </summary>
public bool Dequeue(out BattleCharacter battle) {
public bool Dequeue(out DataCombatRole battle) {
battle = queue.Count > 0 ? queue.Dequeue() : null;
return battle != null;
}
@@ -0,0 +1,81 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 战斗报告
/// </summary>
public class BattleReport {
/// <summary> 战斗消息 </summary>
public List<BattleMessage> messages;
}
/// <summary>
/// 战斗消息
/// </summary>
public class BattleMessage {
}
/// <summary>
/// 普通攻击 - 战斗消息
/// </summary>
public class MessageNormalAttack : BattleMessage {
/// <summary> 攻击者 </summary>
public DataCombatRole attacker;
/// <summary> 命中值 </summary>
public int hit;
/// <summary> 伤害值 </summary>
public int damage;
/// <summary> 被攻击者 </summary>
public DataCombatRole attacked;
/// <summary> 护甲等级 </summary>
public int armorClass;
/// <summary> 设置攻击者 </summary>
public void Settings(DataCombatRole attacker, int hit, int damage) {
this.attacker = attacker;
this.hit = hit;
this.damage = damage;
}
/// <summary> 设置被攻击者 </summary>
public void Settings(DataCombatRole attacked, int armorClass) {
this.attacked = attacked;
this.armorClass = armorClass;
}
public override string ToString() {
return $"{attacker.name}{Dynamics()}{attacked.name}({armorClass}){attacked.name}{Result()}";
}
/// <summary> 动态修饰词 </summary>
private string Dynamics() {
return $"使用长剑劈向({hit})";
}
/// <summary> 结果修饰词 </summary>
private string Result() {
return hit <= armorClass ? Miss() : Hit();
}
// 未命中的多种情况
private string Miss() {
string[] missText = new string[] {
"轻松避开了这一击!",
"巧妙地闪开了!",
"险之又险地躲过了!",
"成功格挡住了!"
};
return RandomChoice(missText);
}
// 命中的情况,可根据伤害量或是否暴击细分
private string Hit() {
string[] hitText = new string[] {
$"躲避不及遭受到了{damage}点伤害!",
$"被狠狠击中,承受了{damage}点伤害!",
$"格挡失败受到了{damage}点伤害!",
};
return RandomChoice(hitText);
}
// 辅助方法:随机选择一个字符串,增加多样性
private string RandomChoice(params string[] options) {
if (options.Length == 0) return "";
return options[Random.Range(0, options.Length)];
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: b4cb406221da1364f97a333bf1e3442c
guid: 26a3fb20ae1a54143ab478049f4acd8e
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -9,6 +9,8 @@ using UnityEngine;
/// 战斗 - 模拟器
/// </summary>
public class BattleSimulator {
/// <summary> 当前行动 </summary>
public DataCombatRole actionRole;
/// <summary> 战斗队列 </summary>
public BattleQueue battleQueue = new BattleQueue();
@@ -18,8 +20,11 @@ public class BattleSimulator {
public Dictionary<PhaseType, IPhase> dictionary = new Dictionary<PhaseType, IPhase>();
public BattleSimulator(BattleTeam team1, BattleTeam team2) {
team1.Initial(1);
team2.Initial(2);
team1.Initial();
team2.Initial();
team1.Settings(1, 1);
team2.Settings(2, 1);
battleQueue.Add(team1.battles);
battleQueue.Add(team2.battles);
@@ -28,27 +33,16 @@ public class BattleSimulator {
dictionary.Add(PhaseType., new PhaseAssault(this));
dictionary.Add(PhaseType., new PhaseFormal(this));
dictionary.Add(PhaseType., new PhaseAction(this));
dictionary.Add(PhaseType., new PhaseActionRoleSelect(this));
dictionary.Add(PhaseType., new PhaseActionRoleAttack(this));
dictionary.Add(PhaseType., new PhaseFinish(this));
Transition(PhaseType.);
}
public void Update() {
currentPhase?.UpdatePhase();
}
/// <summary> 阶段过渡 </summary>
public void Transition(PhaseType phaseType) {
// 检查阶段字典中是否存在指定的阶段类型
if (dictionary.TryGetValue(phaseType, out IPhase newPhase)) {
// 如果存在则更新当前阶段
currentPhase?.QuitPhase();
currentPhase = newPhase;
currentPhase?.StartPhase();
// Debug.Log($"战斗阶段已转换为: {phaseType}");
}
else {
// 不存在时输出警告信息
Debug.LogWarning($"阶段字典中不存在 {phaseType} 对应的阶段实现");
}
if (!dictionary.TryGetValue(phaseType, out IPhase newPhase)) { return; }
currentPhase = newPhase;
currentPhase?.Execute();
}
}
@@ -0,0 +1,10 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 战斗技能
/// </summary>
public class BattleSkill {
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f4f5e0db8e96cfd4d8d9243f4057f99a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+14 -4
View File
@@ -11,7 +11,7 @@ public class BattleTeam {
/// <summary> 原始数据 </summary>
public List<DataCharacter> characters = new List<DataCharacter>();
/// <summary> 战斗数据 </summary>
public List<BattleCharacter> battles = new List<BattleCharacter>();
public List<DataCombatRole> battles = new List<DataCombatRole>();
/// <summary> 添加角色 </summary>
public void Add(List<DataCharacter> list) {
@@ -26,8 +26,18 @@ public class BattleTeam {
characters.Remove(character);
}
/// <summary> 战斗初始化 </summary>
public void Initial(int id) {
characters.ForEach(obj => battles.Add(new BattleCharacter(obj, id)));
/// <summary> 初始化 </summary>
public void Initial() {
characters.ForEach(Initial);
}
/// <summary> 初始化 </summary>
public void Initial(DataCharacter character) {
DataCombatRole role = new DataCombatRole(character);
role.Initial();
battles.Add(role);
}
/// <summary> 战斗编队 </summary>
public void Settings(int team, int position) {
battles.ForEach(obj => obj.Settings(team, position));
}
}