행복도 시스템 해금제: 회관 Lv3 + 햇볕 데크 설치 시 개방 (소프트락 수정)
- 해금 전: 행복도 증감·파업 로직 완전 비활성, 속도 배율 중립, UI에서 💗 숨김 → 초반에 행복도를 올릴 수단이 없어 파업 소프트락에 걸리던 문제 해결 - 해금 조건 달성 시 촌장 냥이가 재등장해 행복도 시스템 안내 (1회) - 해금 순간 전원 행복도 80으로 초기화 - 기존 세이브 마이그레이션: 조건 미충족이면 파업 해제 + 행복도 리셋, 이미 충족한 마을은 안내 생략 - 햇볕 데크 설명에 해금 역할 명시 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
이 커밋은 다음에 포함됨:
+53
-3
@@ -158,8 +158,9 @@ export function fullnessPenalty(cat: Cat): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** 행복도 배율: 80↑ +10%, 20~49 -30% */
|
||||
/** 행복도 배율: 80↑ +10%, 50 미만 -30% (시스템 해금 전엔 중립) */
|
||||
export function happinessMul(cat: Cat): number {
|
||||
if (!state?.happinessUnlocked) return 1;
|
||||
const h = cat.status.happiness;
|
||||
if (h >= 80) return 1.1;
|
||||
if (h < 50) return 0.7;
|
||||
@@ -306,6 +307,20 @@ export const engine = {
|
||||
state.decors ??= [];
|
||||
state.tutorialStep ??= 99; // 기존 마을은 튜토리얼 생략
|
||||
state.coins ??= 0;
|
||||
if (state.happinessUnlocked === undefined) {
|
||||
const deckBuilt = state.buildings.some(
|
||||
(b) => b.type === "sun_deck" && b.constructionUntil === undefined,
|
||||
);
|
||||
state.happinessUnlocked = state.hall.level >= 3 && deckBuilt;
|
||||
state.happinessIntroSeen = state.happinessUnlocked; // 기존 해금 유저는 안내 생략
|
||||
if (!state.happinessUnlocked) {
|
||||
// 해금 전 소프트락 방지: 파업 해제 + 행복도 초기화
|
||||
for (const c of state.cats) {
|
||||
if (c.state === "striking") c.state = null;
|
||||
c.status.happiness = 80;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 보드 개편(크기·풋프린트 변경) 시 건물 위치를 새 기본값으로 재배치
|
||||
if (state.boardVersion !== BOARD_VERSION) {
|
||||
for (const b of state.buildings)
|
||||
@@ -332,6 +347,12 @@ export const engine = {
|
||||
return r;
|
||||
},
|
||||
|
||||
/** 행복도 안내 확인 처리 */
|
||||
markHappinessIntroSeen() {
|
||||
if (!state) return;
|
||||
state.happinessIntroSeen = true;
|
||||
},
|
||||
|
||||
/** 튜토리얼 진행 갱신 (단계 진입 시 촌장 냥이의 지원 지급) */
|
||||
setTutorialStep(step: number) {
|
||||
if (!state) return;
|
||||
@@ -457,6 +478,18 @@ export const engine = {
|
||||
}
|
||||
}
|
||||
|
||||
// 행복도 시스템 해금: 회관 Lv3 + 햇볕 데크 완공
|
||||
if (
|
||||
!state.happinessUnlocked &&
|
||||
state.hall.level >= 3 &&
|
||||
state.buildings.some(
|
||||
(b) => b.type === "sun_deck" && !isUnderConstruction(b),
|
||||
)
|
||||
) {
|
||||
state.happinessUnlocked = true;
|
||||
for (const c of state.cats) c.status.happiness = 80; // 산뜻하게 시작
|
||||
}
|
||||
|
||||
// ---------- 체력·휴식·행복도 (Phase B) ----------
|
||||
const houses = state.buildings.filter(
|
||||
(b) => b.type === "cat_house" && !isUnderConstruction(b),
|
||||
@@ -500,7 +533,8 @@ export const engine = {
|
||||
const inHouse = houses.length > 0 && idx >= 0 && idx < houseCapacity;
|
||||
const recover = inHouse ? HOUSE_RECOVER_PER_SEC : REST_RECOVER_PER_SEC;
|
||||
st.energy = Math.min(cat.stats.stamina, st.energy + recover * dt);
|
||||
st.happiness = Math.min(100, st.happiness + (3 / 60) * gainMul * dt);
|
||||
if (state.happinessUnlocked)
|
||||
st.happiness = Math.min(100, st.happiness + (3 / 60) * gainMul * dt);
|
||||
if (st.energy >= cat.stats.stamina) tryReturn(cat);
|
||||
} else if (cat.assignedTo) {
|
||||
st.energy = Math.max(0, st.energy - ENERGY_DRAIN_PER_SEC * sturdyMul * dt);
|
||||
@@ -519,7 +553,8 @@ export const engine = {
|
||||
);
|
||||
}
|
||||
|
||||
// 행복도 증감
|
||||
// 행복도 증감 (시스템 해금 후에만)
|
||||
if (state.happinessUnlocked) {
|
||||
if (st.fullness >= 80)
|
||||
st.happiness = Math.min(100, st.happiness + (1 / 60) * gainMul * dt);
|
||||
if (st.fullness <= 0)
|
||||
@@ -557,6 +592,7 @@ export const engine = {
|
||||
}
|
||||
if (cat.state === "striking" && st.happiness >= STRIKE_RESUME)
|
||||
tryReturn(cat);
|
||||
} // happinessUnlocked
|
||||
}
|
||||
|
||||
state.updatedAt = Date.now();
|
||||
@@ -675,6 +711,20 @@ export const engine = {
|
||||
state.decors ??= [];
|
||||
state.tutorialStep ??= 99; // 기존 마을은 튜토리얼 생략
|
||||
state.coins ??= 0;
|
||||
if (state.happinessUnlocked === undefined) {
|
||||
const deckBuilt = state.buildings.some(
|
||||
(b) => b.type === "sun_deck" && b.constructionUntil === undefined,
|
||||
);
|
||||
state.happinessUnlocked = state.hall.level >= 3 && deckBuilt;
|
||||
state.happinessIntroSeen = state.happinessUnlocked; // 기존 해금 유저는 안내 생략
|
||||
if (!state.happinessUnlocked) {
|
||||
// 해금 전 소프트락 방지: 파업 해제 + 행복도 초기화
|
||||
for (const c of state.cats) {
|
||||
if (c.state === "striking") c.state = null;
|
||||
c.status.happiness = 80;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 같은 타일의 기존 장식 제거 후 배치
|
||||
state.decors = state.decors.filter(
|
||||
(d) => !(d.pos.i === pos.i && d.pos.j === pos.j),
|
||||
|
||||
새 이슈에서 참조
사용자 차단