- StoryManager: 剧情管理器 - DialogueBox: 对话框组件(带打字机效果) - CharacterView: 立绘组件 - ChoiceButton: 选项按钮 - AffectionSystem: 好感度系统 - chapter1.json: 示例剧情
260 lines
6.7 KiB
TypeScript
260 lines
6.7 KiB
TypeScript
import { _decorator, Component, Label, Node } from 'cc';
|
||
|
||
const { ccclass, property } = _decorator;
|
||
|
||
// 好感度等级
|
||
export enum AffectionLevel {
|
||
STRANGER = '陌生人', // 0-20
|
||
ACQUAINTANCE = '认识的人', // 21-40
|
||
FRIEND = '朋友', // 41-60
|
||
CLOSE = '恋人未满', // 61-80
|
||
LOVER = '恋人' // 81-100
|
||
}
|
||
|
||
// 角色好感度数据
|
||
interface CharacterAffection {
|
||
value: number;
|
||
level: AffectionLevel;
|
||
events: string[]; // 触发过的事件
|
||
}
|
||
|
||
// 好感度变化事件
|
||
interface AffectionEvent {
|
||
characterId: string;
|
||
change: number;
|
||
reason: string;
|
||
timestamp: number;
|
||
}
|
||
|
||
@ccclass('AffectionSystem')
|
||
export class AffectionSystem extends Component {
|
||
@property(Node)
|
||
affectionDisplay: Node;
|
||
|
||
// 角色好感度
|
||
private affection: Map<string, CharacterAffection> = new Map();
|
||
|
||
// 好感度变化历史
|
||
private history: AffectionEvent[] = [];
|
||
|
||
// 最大好感度
|
||
private maxAffection: number = 100;
|
||
|
||
onLoad() {
|
||
// 初始化角色好感度
|
||
this.initCharacters(['li_ze_yan', 'xu_mo', 'zhou_qi_luo', 'bai_qi']);
|
||
}
|
||
|
||
/**
|
||
* 初始化角色
|
||
*/
|
||
initCharacters(characterIds: string[]) {
|
||
characterIds.forEach(id => {
|
||
this.affection.set(id, {
|
||
value: 0,
|
||
level: AffectionLevel.STRANGER,
|
||
events: []
|
||
});
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 更改好感度
|
||
*/
|
||
changeAffection(changes: { [key: string]: number }, reason: string = '选项') {
|
||
for (const [characterId, change] of Object.entries(changes)) {
|
||
const current = this.affection.get(characterId);
|
||
if (!current) {
|
||
console.warn(`角色不存在: ${characterId}`);
|
||
continue;
|
||
}
|
||
|
||
// 计算新值
|
||
const oldValue = current.value;
|
||
const newValue = Math.max(0, Math.min(this.maxAffection, current.value + change));
|
||
|
||
// 更新数据
|
||
current.value = newValue;
|
||
current.level = this.calculateLevel(newValue);
|
||
|
||
// 记录事件
|
||
current.events.push(reason);
|
||
|
||
// 记录历史
|
||
this.history.push({
|
||
characterId,
|
||
change,
|
||
reason,
|
||
timestamp: Date.now()
|
||
});
|
||
|
||
console.log(`好感度变化: ${characterId} ${oldValue} -> ${newValue} (${change > 0 ? '+' : ''}${change})`);
|
||
|
||
// 显示提示
|
||
this.showAffectionChange(characterId, change);
|
||
}
|
||
|
||
// 更新显示
|
||
this.updateDisplay();
|
||
}
|
||
|
||
/**
|
||
* 计算好感度等级
|
||
*/
|
||
private calculateLevel(value: number): AffectionLevel {
|
||
if (value <= 20) return AffectionLevel.STRANGER;
|
||
if (value <= 40) return AffectionLevel.ACQUAINTANCE;
|
||
if (value <= 60) return AffectionLevel.FRIEND;
|
||
if (value <= 80) return AffectionLevel.CLOSE;
|
||
return AffectionLevel.LOVER;
|
||
}
|
||
|
||
/**
|
||
* 获取角色好感度
|
||
*/
|
||
getAffection(characterId: string): number {
|
||
const data = this.affection.get(characterId);
|
||
return data ? data.value : 0;
|
||
}
|
||
|
||
/**
|
||
* 获取角色好感度等级
|
||
*/
|
||
getAffectionLevel(characterId: string): AffectionLevel {
|
||
const data = this.affection.get(characterId);
|
||
return data ? data.level : AffectionLevel.STRANGER;
|
||
}
|
||
|
||
/**
|
||
* 获取所有角色好感度
|
||
*/
|
||
getAllAffection(): Map<string, CharacterAffection> {
|
||
return this.affection;
|
||
}
|
||
|
||
/**
|
||
* 检查是否达到特定等级
|
||
*/
|
||
hasReachedLevel(characterId: string, level: AffectionLevel): boolean {
|
||
const currentLevel = this.getAffectionLevel(characterId);
|
||
const levelOrder = [
|
||
AffectionLevel.STRANGER,
|
||
AffectionLevel.ACQUAINTANCE,
|
||
AffectionLevel.FRIEND,
|
||
AffectionLevel.CLOSE,
|
||
AffectionLevel.LOVER
|
||
];
|
||
|
||
return levelOrder.indexOf(currentLevel) >= levelOrder.indexOf(level);
|
||
}
|
||
|
||
/**
|
||
* 获取最高好感的角色
|
||
*/
|
||
getHighestAffectionCharacter(): string {
|
||
let maxId = '';
|
||
let maxValue = -1;
|
||
|
||
this.affection.forEach((data, id) => {
|
||
if (data.value > maxValue) {
|
||
maxValue = data.value;
|
||
maxId = id;
|
||
}
|
||
});
|
||
|
||
return maxId;
|
||
}
|
||
|
||
/**
|
||
* 重置好感度
|
||
*/
|
||
reset() {
|
||
this.affection.forEach((data) => {
|
||
data.value = 0;
|
||
data.level = AffectionLevel.STRANGER;
|
||
data.events = [];
|
||
});
|
||
this.history = [];
|
||
this.updateDisplay();
|
||
}
|
||
|
||
/**
|
||
* 保存存档
|
||
*/
|
||
save(): string {
|
||
const saveData = {
|
||
affection: Object.fromEntries(this.affection),
|
||
history: this.history
|
||
};
|
||
return JSON.stringify(saveData);
|
||
}
|
||
|
||
/**
|
||
* 加载存档
|
||
*/
|
||
load(jsonString: string) {
|
||
try {
|
||
const saveData = JSON.parse(jsonString);
|
||
|
||
if (saveData.affection) {
|
||
this.affection = new Map(Object.entries(saveData.affection));
|
||
}
|
||
|
||
if (saveData.history) {
|
||
this.history = saveData.history;
|
||
}
|
||
|
||
this.updateDisplay();
|
||
} catch (e) {
|
||
console.error('加载存档失败:', e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新显示
|
||
*/
|
||
private updateDisplay() {
|
||
if (!this.affectionDisplay) return;
|
||
|
||
// 遍历显示节点并更新
|
||
// 这里需要根据实际UI结构来实现
|
||
// 示例:假设子节点名为角色ID
|
||
this.affectionDisplay.children.forEach(child => {
|
||
const characterId = child.name;
|
||
const data = this.affection.get(characterId);
|
||
|
||
if (data) {
|
||
const label = child.getComponent(Label);
|
||
if (label) {
|
||
label.string = `${characterId}: ${data.value} (${data.level})`;
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 显示好感度变化
|
||
*/
|
||
private showAffectionChange(characterId: string, change: number) {
|
||
// 可以在这里添加飘字效果
|
||
// 示例:
|
||
// this.showFloatingText(`${change > 0 ? '+' : ''}${change}`, characterId);
|
||
|
||
console.log(`[${characterId}] 好感度 ${change > 0 ? '+' : ''}${change}`);
|
||
}
|
||
|
||
/**
|
||
* 获取好感度历史
|
||
*/
|
||
getHistory(): AffectionEvent[] {
|
||
return this.history;
|
||
}
|
||
|
||
/**
|
||
* 获取特定角色的历史
|
||
*/
|
||
getCharacterHistory(characterId: string): AffectionEvent[] {
|
||
return this.history.filter(e => e.characterId === characterId);
|
||
}
|
||
}
|