feat(items): add various new items with unique effects and triggers

- Added '병법24편' book item to enhance intelligence by 13.
- Added '오자병법' book item to enhance intelligence by 14.
- Added '한비자' book item to enhance intelligence by 14.
- Added '노자' book item to enhance intelligence by 15.
- Added '손자병법' book item to enhance intelligence by 15.
- Introduced '동작' item to increase dexterity by 20%.
- Implemented '옥벽' item for a 20% chance to steal resources in battle.
- Created '상한잡병론' book item to improve city healing efficiency by 50%.
- Developed '정력견혈산' book item to enhance city healing efficiency by 100%.
- Added '청낭서' book item to improve city healing efficiency by 50%.
- Introduced '태평청령' book item to improve city healing efficiency by 50%.
- Added '매화수전' item for a 50% sniping chance during strategy attempts.
- Created '비도' item for a 50% sniping chance during strategy attempts.
- Developed '수극' item for a one-time sniping action at the start of battle.
- Introduced '삼황내문' item to halt enemy phases during defense.
- Added '평만지장도' item to reduce cooldown for national strategies by 20%.
- Created '주판' item to enhance resource acquisition success and quantity.
- Developed '박혁론' item to negate enemy strategies and rage effects.
- Introduced '전국책' item to increase damage by 30% on successful strategies.
- Added '낙주' item to reduce conscription costs and maintain population.
- Created '오악진형도' item to increase damage against regional units.
- Developed '둔갑천서' item to enhance critical hit probability by 20%.
- Introduced '서촉지형도' item to increase attack phase by 2.
- Added '논어집해' item to improve strategy success rate and damage.
- Created '태평요술' item to enhance evasion probability by 20%.
- Developed '단결도' item to increase training efficiency by 15.
- Introduced '철벽서' item to increase training efficiency by 15.
- Created '청주' item to provide a one-time training boost of 40.
This commit is contained in:
2026-01-06 16:40:47 +00:00
parent 0cfdebbb08
commit 4f23173efe
117 changed files with 3044 additions and 20 deletions
@@ -0,0 +1,32 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_간파_노군입산부';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '노군입산부',
name: '노군입산부(간파)',
info: '[전투] 상대 회피 확률 -25%p, 상대 필살 확률 -10%p',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcOpposeStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === 'warAvoidRatio') {
return (value as number) - 0.25;
}
if (statName === 'warCriticalRatio') {
return (value as number) - 0.1;
}
return value;
} as NonNullable<ItemModule['onCalcOpposeStat']>,
};
@@ -0,0 +1,98 @@
import { LogFormat } from '@sammo-ts/logic/logging/types.js';
import { TriggerPriority } from '@sammo-ts/logic/triggers/core.js';
import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js';
import type { WarUnit } from '@sammo-ts/logic/war/units.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_격노_구정신단경';
class CheRageAttemptTrigger extends BaseWarUnitTrigger {
constructor(unit: WarUnit, raiseType: number) {
super(unit, TriggerPriority.Body + 400, raiseType);
}
protected actionWar(
self: WarUnit,
oppose: WarUnit,
_selfEnv: Record<string, unknown>,
_opposeEnv: Record<string, unknown>
): boolean {
if (!oppose.hasActivatedSkill('필살') && !oppose.hasActivatedSkill('회피')) {
return true;
}
if (self.hasActivatedSkill('격노불가')) {
return true;
}
if (oppose.hasActivatedSkill('필살')) {
self.activateSkill('격노');
oppose.deactivateSkill('회피');
if (self.isAttacker() && self.rng.nextBool(0.5)) {
self.activateSkill('진노');
}
} else if (self.rng.nextBool(0.25)) {
self.activateSkill('격노');
oppose.deactivateSkill('회피');
if (self.isAttacker() && self.rng.nextBool(0.5)) {
self.activateSkill('진노');
}
}
return true;
}
}
class CheRageActivateTrigger extends BaseWarUnitTrigger {
constructor(unit: WarUnit, raiseType: number) {
super(unit, TriggerPriority.Post + 600, raiseType);
}
protected actionWar(
self: WarUnit,
oppose: WarUnit,
_selfEnv: Record<string, unknown>,
_opposeEnv: Record<string, unknown>
): boolean {
if (!self.hasActivatedSkill('격노')) {
return true;
}
const targetAct = oppose.hasActivatedSkill('필살') ? '필살 공격' : '회피 시도';
const isJinno = self.hasActivatedSkill('진노');
const reaction = isJinno ? '진노' : '격노';
self.getLogger().pushGeneralBattleDetailLog(`상대의 ${targetAct}에 <C>${reaction}</>했다!</>`, LogFormat.PLAIN);
oppose
.getLogger()
.pushGeneralBattleDetailLog(`${targetAct}에 상대가 <R>${reaction}</>했다!</>`, LogFormat.PLAIN);
if (isJinno) {
self.addBonusPhase(1);
}
self.multiplyWarPowerMultiply(self.criticalDamage());
return true;
}
}
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '구정신단경',
name: '구정신단경(격노)',
info: '[전투] 상대방 필살 시 격노(필살) 발동, 회피 시도시 25% 확률로 격노 발동, 공격 시 일정 확률로 진노(1페이즈 추가), 격노마다 대미지 5% 추가 중첩',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
getWarPowerMultiplier: (_context, unit, _oppose) => {
const activatedCnt = unit.hasActivatedSkillOnLog('격노');
return [1 + 0.05 * activatedCnt, 1];
},
getBattlePhaseTriggerList: (context) => {
if (!context.unit) return null;
return new WarTriggerCaller(
new CheRageAttemptTrigger(context.unit, BaseWarUnitTrigger.TYPE_ITEM),
new CheRageActivateTrigger(context.unit, BaseWarUnitTrigger.TYPE_ITEM)
);
},
};
@@ -0,0 +1,35 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_계략_삼략';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '삼략',
name: '삼략(계략)',
info: '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p<br>[전투] 계략 시도 확률 +10%p, 계략 성공 확률 +10%p',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcDomestic: (_context, turnType, varType, value) => {
if (turnType === '계략' && varType === 'success') {
return value + 0.2;
}
return value;
},
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === 'warMagicTrialProb' || statName === 'warMagicSuccessProb') {
return (value as number) + 0.1;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,35 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_계략_육도';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '육도',
name: '육도(계략)',
info: '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p<br>[전투] 계략 시도 확률 +10%p, 계략 성공 확률 +10%p',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcDomestic: (_context, turnType, varType, value) => {
if (turnType === '계략' && varType === 'success') {
return value + 0.2;
}
return value;
},
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === 'warMagicTrialProb' || statName === 'warMagicSuccessProb') {
return (value as number) + 0.1;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,22 @@
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_계략_이추';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '이추',
name: '이추(계략)',
info: '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p',
slot: 'item',
cost: 1000,
buyable: true,
consumable: true,
reqSecu: 1000,
unique: false,
onCalcDomestic: (_context, turnType, varType, value) => {
if (turnType === '계략' && varType === 'success') {
return value + 0.2;
}
return value;
},
};
@@ -0,0 +1,22 @@
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_계략_향낭';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '향낭',
name: '향낭(계략)',
info: '[계략] 화계·탈취·파괴·선동 : 성공률 +50%p',
slot: 'item',
cost: 3000,
buyable: true,
consumable: true,
reqSecu: 2000,
unique: false,
onCalcDomestic: (_context, turnType, varType, value) => {
if (turnType === '계략' && varType === 'success') {
return value + 0.5;
}
return value;
},
};
@@ -0,0 +1,22 @@
import { WarUnitCity } from '@sammo-ts/logic/war/units.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = {
key: 'che_공성_묵자',
rawName: '묵자',
name: '묵자(공성)',
info: '[전투] 성벽 공격 시 대미지 +50%',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: true,
getWarPowerMultiplier: (_context, unit) => {
const oppose = unit.getOppose();
if (oppose instanceof WarUnitCity) {
return [1.5, 1];
}
return [1, 1];
},
};
@@ -0,0 +1,22 @@
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_내정_납금박산로';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '납금박산로',
name: '납금박산로(내정)',
info: '[내정] 내정 성공률 +15%p',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcDomestic: (_context, turnType, varType, value) => {
if (['상업', '농업', '기술', '성벽', '수비', '치안', '민심', '인구'].includes(turnType)) {
if (varType === 'success') return value + 0.15;
}
return value;
},
};
@@ -0,0 +1,39 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_농성_위공자병법';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '위공자병법',
name: '위공자병법(농성)',
info: '[계략] 장수 주둔 도시 화계·탈취·파괴·선동 : 성공률 -30%p<br>[전투] 상대 계략 시도 확률 -10%p, 상대 계략 성공 확률 -10%p',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === 'sabotageDefence') {
return (value as number) + 0.3;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
onCalcOpposeStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === 'warMagicTrialProb' || statName === 'warMagicSuccessProb') {
return (value as number) - 0.1;
}
return value;
} as NonNullable<ItemModule['onCalcOpposeStat']>,
};
@@ -0,0 +1,39 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_농성_주서음부';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '주서음부',
name: '주서음부(농성)',
info: '[계략] 장수 주둔 도시 화계·탈취·파괴·선동 : 성공률 -30%p<br>[전투] 상대 계략 시도 확률 -10%p, 상대 계략 성공 확률 -10%p',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === 'sabotageDefence') {
return (value as number) + 0.3;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
onCalcOpposeStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === 'warMagicTrialProb' || statName === 'warMagicSuccessProb') {
return (value as number) - 0.1;
}
return value;
} as NonNullable<ItemModule['onCalcOpposeStat']>,
};
@@ -0,0 +1,44 @@
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { clamp } from '@sammo-ts/logic/war/utils.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_능력치_무력_두강주';
const resolveNumber = (value: unknown, fallback = 0): number =>
typeof value === 'number' && Number.isFinite(value) ? value : fallback;
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '두강주',
name: '두강주(무력)',
info: '[능력치] 무력 +5 +(4년마다 +1)',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
if (statName === 'strength') {
const auxObj = aux as Record<string, unknown> | undefined;
const year = resolveNumber(auxObj?.['year']);
const startYear = resolveNumber(auxObj?.['startYear']);
const maxTechLevel = resolveNumber(auxObj?.['maxTechLevel'], 12);
const relYear = Math.max(0, year - startYear);
const bonus = 5 + clamp(Math.floor(relYear / 4), 0, maxTechLevel);
if (Array.isArray(value)) {
return [value[0] + bonus, value[1] + bonus];
}
return (value as number) + bonus;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,44 @@
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { clamp } from '@sammo-ts/logic/war/utils.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_능력치_지력_이강주';
const resolveNumber = (value: unknown, fallback = 0): number =>
typeof value === 'number' && Number.isFinite(value) ? value : fallback;
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '이강주',
name: '이강주(지력)',
info: '[능력치] 지력 +5 +(4년마다 +1)',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
if (statName === 'intelligence') {
const auxObj = aux as Record<string, unknown> | undefined;
const year = resolveNumber(auxObj?.['year']);
const startYear = resolveNumber(auxObj?.['startYear']);
const maxTechLevel = resolveNumber(auxObj?.['maxTechLevel'], 12);
const relYear = Math.max(0, year - startYear);
const bonus = 5 + clamp(Math.floor(relYear / 4), 0, maxTechLevel);
if (Array.isArray(value)) {
return [value[0] + bonus, value[1] + bonus];
}
return (value as number) + bonus;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,44 @@
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { clamp } from '@sammo-ts/logic/war/utils.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_능력치_통솔_보령압주';
const resolveNumber = (value: unknown, fallback = 0): number =>
typeof value === 'number' && Number.isFinite(value) ? value : fallback;
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '보령압주',
name: '보령압주(통솔)',
info: '[능력치] 통솔 +5 +(4년마다 +1)',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
if (statName === 'leadership') {
const auxObj = aux as Record<string, unknown> | undefined;
const year = resolveNumber(auxObj?.['year']);
const startYear = resolveNumber(auxObj?.['startYear']);
const maxTechLevel = resolveNumber(auxObj?.['maxTechLevel'], 12);
const relYear = Math.max(0, year - startYear);
const bonus = 5 + clamp(Math.floor(relYear / 4), 0, maxTechLevel);
if (Array.isArray(value)) {
return [value[0] + bonus, value[1] + bonus];
}
return (value as number) + bonus;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,13 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_02_조랑',
rawName: '조랑',
slot: 'horse',
statName: 'leadership',
statValue: 2,
cost: 3000,
buyable: true,
reqSecu: 2000,
});
@@ -0,0 +1,13 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_03_노새',
rawName: '노새',
slot: 'horse',
statName: 'leadership',
statValue: 3,
cost: 4500,
buyable: true,
reqSecu: 2500,
});
@@ -0,0 +1,13 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_04_나귀',
rawName: '나귀',
slot: 'horse',
statName: 'leadership',
statValue: 4,
cost: 6000,
buyable: true,
reqSecu: 3000,
});
@@ -0,0 +1,13 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_05_갈색마',
rawName: '갈색마',
slot: 'horse',
statName: 'leadership',
statValue: 5,
cost: 7500,
buyable: true,
reqSecu: 3500,
});
@@ -0,0 +1,34 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const baseModule = createStatItemModule({
key: 'che_명마_07_기주마',
rawName: '기주마',
slot: 'horse',
statName: 'leadership',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
extraInfo: '[전투] 공격 시 페이즈 +1',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcStat: function (
context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
const newValue = baseModule.onCalcStat!(context as never, statName as never, value as never, aux);
if (statName === 'initWarPhase') {
return (newValue as number) + 1;
}
return newValue;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,27 @@
import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js';
import { CheRetreatNoWoundTrigger } from '@sammo-ts/logic/war/triggers/che_퇴각부상무효.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const baseModule = createStatItemModule({
key: 'che_명마_07_백마',
rawName: '백마',
slot: 'horse',
statName: 'leadership',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
extraInfo: '[전투] 전투 종료로 인한 부상 없음',
});
export const itemModule: ItemModule = {
...baseModule,
getBattleInitTriggerList: (context) => {
if (!context.unit) {
return null;
}
return new WarTriggerCaller(new CheRetreatNoWoundTrigger(context.unit));
},
};
@@ -0,0 +1,45 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const baseModule = createStatItemModule({
key: 'che_명마_07_백상',
rawName: '백상',
slot: 'horse',
statName: 'leadership',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
extraInfo: '[전투] 공격력 +20%, 소모 군량 +10%, 공격 시 페이즈 -1',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcStat: function (
context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
const newValue = baseModule.onCalcStat!(
context as unknown as GeneralActionContext,
statName as unknown as GeneralStatName,
value as unknown as number,
aux
);
if (statName === 'killRice') {
return (newValue as number) * 1.1;
}
if (statName === 'initWarPhase') {
return (newValue as number) - 1;
}
return newValue;
} as NonNullable<ItemModule['onCalcStat']>,
getWarPowerMultiplier() {
return [1.2, 1];
},
};
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_07_오환마',
rawName: '오환마',
slot: 'horse',
statName: 'leadership',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_08_양주마',
rawName: '양주마',
slot: 'horse',
statName: 'leadership',
statValue: 8,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_08_흉노마',
rawName: '흉노마',
slot: 'horse',
statName: 'leadership',
statValue: 8,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_09_과하마',
rawName: '과하마',
slot: 'horse',
statName: 'leadership',
statValue: 9,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_09_의남백마',
rawName: '의남백마',
slot: 'horse',
statName: 'leadership',
statValue: 9,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_10_대완마',
rawName: '대완마',
slot: 'horse',
statName: 'leadership',
statValue: 10,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_10_옥추마',
rawName: '옥추마',
slot: 'horse',
statName: 'leadership',
statValue: 10,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_11_서량마',
rawName: '서량마',
slot: 'horse',
statName: 'leadership',
statValue: 11,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_11_화종마',
rawName: '화종마',
slot: 'horse',
statName: 'leadership',
statValue: 11,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,42 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const baseModule = createStatItemModule({
key: 'che_명마_12_옥란백용구',
rawName: '옥란백용구',
slot: 'horse',
statName: 'leadership',
statValue: 12,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
extraInfo: '[전투] 남은 병력이 적을수록 회피 확률 증가. 최대 +50%p',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcStat: function (
context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
const newValue = baseModule.onCalcStat!(
context as unknown as GeneralActionContext,
statName as unknown as GeneralStatName,
value as unknown as number,
aux
);
if (statName === 'warAvoidRatio') {
const { leadership } = (context as unknown as GeneralActionContext).general.stats;
const crewL = (context as unknown as GeneralActionContext).general.crew / 100;
const boost = (1 - crewL / leadership) * 0.5;
return (newValue as number) + Math.min(Math.max(boost, 0), 0.5);
}
return newValue;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_13_적로',
rawName: '적로',
slot: 'horse',
statName: 'leadership',
statValue: 13,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_13_절영',
rawName: '절영',
slot: 'horse',
statName: 'leadership',
statValue: 13,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_14_적란마',
rawName: '적란마',
slot: 'horse',
statName: 'leadership',
statValue: 14,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_14_조황비전',
rawName: '조황비전',
slot: 'horse',
statName: 'leadership',
statValue: 14,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_15_적토마',
rawName: '적토마',
slot: 'horse',
statName: 'leadership',
statValue: 15,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_명마_15_한혈마',
rawName: '한혈마',
slot: 'horse',
statName: 'leadership',
statValue: 15,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,29 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_명성_구석';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '구석',
name: '구석(명성)',
info: '명성 +20%',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === 'experience') {
return (value as number) * 1.2;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,13 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_01_단도',
rawName: '단도',
slot: 'weapon',
statName: 'strength',
statValue: 1,
cost: 1000,
buyable: true,
reqSecu: 1000,
});
@@ -0,0 +1,13 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_03_단극',
rawName: '단극',
slot: 'weapon',
statName: 'strength',
statValue: 3,
cost: 4500,
buyable: true,
reqSecu: 2500,
});
@@ -0,0 +1,13 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_04_목검',
rawName: '목검',
slot: 'weapon',
statName: 'strength',
statValue: 4,
cost: 6000,
buyable: true,
reqSecu: 3000,
});
@@ -0,0 +1,13 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_05_죽창',
rawName: '죽창',
slot: 'weapon',
statName: 'strength',
statValue: 5,
cost: 7500,
buyable: true,
reqSecu: 3500,
});
@@ -0,0 +1,13 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_06_소부',
rawName: '소부',
slot: 'weapon',
statName: 'strength',
statValue: 6,
cost: 9000,
buyable: true,
reqSecu: 4000,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_07_동추',
rawName: '동추',
slot: 'weapon',
statName: 'strength',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_07_맥궁',
rawName: '맥궁',
slot: 'weapon',
statName: 'strength',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_07_철쇄',
rawName: '철쇄',
slot: 'weapon',
statName: 'strength',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_07_철편',
rawName: '철편',
slot: 'weapon',
statName: 'strength',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_08_유성추',
rawName: '유성추',
slot: 'weapon',
statName: 'strength',
statValue: 8,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_08_철질여골',
rawName: '철질여골',
slot: 'weapon',
statName: 'strength',
statValue: 8,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_09_쌍철극',
rawName: '쌍철극',
slot: 'weapon',
statName: 'strength',
statValue: 9,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_10_대부',
rawName: '대부',
slot: 'weapon',
statName: 'strength',
statValue: 10,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_10_삼첨도',
rawName: '삼첨도',
slot: 'weapon',
statName: 'strength',
statValue: 10,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_11_고정도',
rawName: '고정도',
slot: 'weapon',
statName: 'strength',
statValue: 11,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_11_이광궁',
rawName: '이광궁',
slot: 'weapon',
statName: 'strength',
statValue: 11,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_12_철척사모',
rawName: '철척사모',
slot: 'weapon',
statName: 'strength',
statValue: 12,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_12_칠성검',
rawName: '칠성검',
slot: 'weapon',
statName: 'strength',
statValue: 12,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_13_사모',
rawName: '사모',
slot: 'weapon',
statName: 'strength',
statValue: 13,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_13_양유기궁',
rawName: '양유기궁',
slot: 'weapon',
statName: 'strength',
statValue: 13,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_14_방천화극',
rawName: '방천화극',
slot: 'weapon',
statName: 'strength',
statValue: 14,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_14_언월도',
rawName: '언월도',
slot: 'weapon',
statName: 'strength',
statValue: 14,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_15_의천검',
rawName: '의천검',
slot: 'weapon',
statName: 'strength',
statValue: 15,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_무기_15_청홍검',
rawName: '청홍검',
slot: 'weapon',
statName: 'strength',
statValue: 15,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,46 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js';
import type { WarUnit } from '@sammo-ts/logic/war/units.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_부적_태현청생부';
class CheAmuletTrigger extends BaseWarUnitTrigger {
constructor(unit: WarUnit) {
super(unit, 0);
}
protected actionWar(self: WarUnit): boolean {
self.activateSkill('저격불가', '부상무효');
return true;
}
}
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '태현청생부',
name: '태현청생부(부적)',
info: '[전투] 저격 불가, 부상 없음',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === ('injuryProb' as unknown as WarStatName)) {
return (value as number) - 1;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
getBattlePhaseTriggerList: (context) => {
if (!context.unit) return null;
return new WarTriggerCaller(new CheAmuletTrigger(context.unit));
},
};
@@ -0,0 +1,28 @@
import { clamp } from '@sammo-ts/logic/war/utils.js';
import { WarUnitGeneral } from '@sammo-ts/logic/war/units.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_불굴_상편';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '상편',
name: '상편(불굴)',
info: '[전투] 남은 병력이 적을수록 공격력 증가. 최대 +60%',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
getWarPowerMultiplier: (_context, unit, _oppose) => {
if (!(unit instanceof WarUnitGeneral)) {
return [1, 1];
}
const general = unit.getGeneral();
const leadership = general.stats.leadership;
const crew = general.crew;
const crewRatio = clamp(crew / (leadership * 100), 0, 1);
return [1 + 0.6 * (1 - crewRatio), 1];
},
};
@@ -0,0 +1,29 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_사기_초선화';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '초선화',
name: '초선화(사기)',
info: '[전투] 사기 보정 +15',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === 'bonusAtmos') {
return (value as number) + 15;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,29 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_사기_춘화첩';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '춘화첩',
name: '춘화첩(사기)',
info: '[전투] 사기 보정 +15',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === 'bonusAtmos') {
return (value as number) + 15;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,39 @@
import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js';
import type { WarUnit } from '@sammo-ts/logic/war/units.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_사기_탁주';
class CheAtmosIncreaseTrigger extends BaseWarUnitTrigger {
private readonly amount: number;
constructor(unit: WarUnit, raiseType: number, amount: number) {
super(unit, 0, raiseType);
this.amount = amount;
}
protected actionWar(self: WarUnit): boolean {
self.addAtmos(this.amount);
this.processConsumableItem();
return true;
}
}
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '탁주',
name: '탁주(사기)',
info: '[전투] 사기 +30(한도 내). 1회용',
slot: 'item',
cost: 1000,
buyable: true,
consumable: true,
reqSecu: 1000,
unique: false,
getBattleInitTriggerList: (context) => {
if (!context.unit) return null;
return new WarTriggerCaller(
new CheAtmosIncreaseTrigger(context.unit, BaseWarUnitTrigger.TYPE_CONSUMABLE_ITEM, 30)
);
},
};
@@ -0,0 +1,23 @@
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_상성보정_과실주';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '과실주',
name: '과실주(상성)',
info: '[전투] 대등/유리한 병종 전투시 공격력 +10%, 피해 -10%',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
getWarPowerMultiplier: (_context, unit, oppose) => {
const attackCoef = unit.getCrewType().getAttackCoef(oppose.getCrewType());
if (attackCoef < 1) {
return [1, 1];
}
return [1.1, 0.9];
},
};
@@ -0,0 +1,40 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const STAT_VALUE = 1;
const baseModule = createStatItemModule({
key: 'che_서적_01_효경전',
rawName: '효경전',
slot: 'book',
statName: 'intelligence',
statValue: STAT_VALUE,
cost: 1000,
buyable: true,
reqSecu: 1000,
extraInfo: '[전투] 계략 시도 확률 +1%p',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcStat: function (
context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
const newValue = baseModule.onCalcStat!(
context as unknown as GeneralActionContext,
statName as unknown as GeneralStatName,
value as unknown as number,
aux
);
if (statName === 'warMagicTrialProb') {
return (newValue as number) + 0.01;
}
return newValue;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,40 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const STAT_VALUE = 2;
const baseModule = createStatItemModule({
key: 'che_서적_02_회남자',
rawName: '회남자',
slot: 'book',
statName: 'intelligence',
statValue: STAT_VALUE,
cost: 3000,
buyable: true,
reqSecu: 2000,
extraInfo: '[전투] 계략 시도 확률 +1%p',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcStat: function (
context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
const newValue = baseModule.onCalcStat!(
context as unknown as GeneralActionContext,
statName as unknown as GeneralStatName,
value as unknown as number,
aux
);
if (statName === 'warMagicTrialProb') {
return (newValue as number) + 0.01;
}
return newValue;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,40 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const STAT_VALUE = 4;
const baseModule = createStatItemModule({
key: 'che_서적_04_건상역주',
rawName: '건상역주',
slot: 'book',
statName: 'intelligence',
statValue: STAT_VALUE,
cost: 6000,
buyable: true,
reqSecu: 3000,
extraInfo: '[전투] 계략 시도 확률 +2%p',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcStat: function (
context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
const newValue = baseModule.onCalcStat!(
context as unknown as GeneralActionContext,
statName as unknown as GeneralStatName,
value as unknown as number,
aux
);
if (statName === 'warMagicTrialProb') {
return (newValue as number) + 0.02;
}
return newValue;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,40 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const STAT_VALUE = 5;
const baseModule = createStatItemModule({
key: 'che_서적_05_여씨춘추',
rawName: '여씨춘추',
slot: 'book',
statName: 'intelligence',
statValue: STAT_VALUE,
cost: 7500,
buyable: true,
reqSecu: 3500,
extraInfo: '[전투] 계략 시도 확률 +3%p',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcStat: function (
context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
const newValue = baseModule.onCalcStat!(
context as unknown as GeneralActionContext,
statName as unknown as GeneralStatName,
value as unknown as number,
aux
);
if (statName === 'warMagicTrialProb') {
return (newValue as number) + 0.03;
}
return newValue;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,40 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const STAT_VALUE = 6;
const baseModule = createStatItemModule({
key: 'che_서적_06_사민월령',
rawName: '사민월령',
slot: 'book',
statName: 'intelligence',
statValue: STAT_VALUE,
cost: 9000,
buyable: true,
reqSecu: 4000,
extraInfo: '[전투] 계략 시도 확률 +3%p',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcStat: function (
context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
const newValue = baseModule.onCalcStat!(
context as unknown as GeneralActionContext,
statName as unknown as GeneralStatName,
value as unknown as number,
aux
);
if (statName === 'warMagicTrialProb') {
return (newValue as number) + 0.03;
}
return newValue;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,33 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const baseModule = createStatItemModule({
key: 'che_서적_07_논어',
rawName: '논어',
slot: 'book',
statName: 'intelligence',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
extraInfo: '[전투] 상대의 계략 성공 확률 -10%p',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcOpposeStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
_aux?: unknown
): unknown {
if (statName === 'warMagicSuccessProb') {
return (value as number) - 0.1;
}
return value;
} as NonNullable<ItemModule['onCalcOpposeStat']>,
};
@@ -0,0 +1,15 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_07_사마법',
rawName: '사마법',
slot: 'book',
statName: 'intelligence',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
extraInfo: '[전투] 상대의 계략을 10% 확률로 되돌림',
});
@@ -0,0 +1,39 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const baseModule = createStatItemModule({
key: 'che_서적_07_위료자',
rawName: '위료자',
slot: 'book',
statName: 'intelligence',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
extraInfo: '[전투] 계략 시도 확률 +20%p',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcStat: function (
context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
aux?: unknown
): unknown {
const newValue = baseModule.onCalcStat!(
context as unknown as GeneralActionContext,
statName as unknown as GeneralStatName,
value as unknown as number,
aux
);
if (statName === 'warMagicTrialProb') {
return (newValue as number) + 0.2;
}
return newValue;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_07_한서',
rawName: '한서',
slot: 'book',
statName: 'intelligence',
statValue: 7,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_08_사기',
rawName: '사기',
slot: 'book',
statName: 'intelligence',
statValue: 8,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_09_역경',
rawName: '역경',
slot: 'book',
statName: 'intelligence',
statValue: 9,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_09_장자',
rawName: '장자',
slot: 'book',
statName: 'intelligence',
statValue: 9,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_10_구국론',
rawName: '구국론',
slot: 'book',
statName: 'intelligence',
statValue: 10,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_10_시경',
rawName: '시경',
slot: 'book',
statName: 'intelligence',
statValue: 10,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_11_상군서',
rawName: '상군서',
slot: 'book',
statName: 'intelligence',
statValue: 11,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,33 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
const baseModule = createStatItemModule({
key: 'che_서적_11_춘추전',
rawName: '춘추전',
slot: 'book',
statName: 'intelligence',
statValue: 11,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
extraInfo: '[전투] 상대의 계략 성공 확률 -10%p',
});
export const itemModule: ItemModule = {
...baseModule,
onCalcOpposeStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown,
_aux?: unknown
): unknown {
if (statName === 'warMagicSuccessProb') {
return (value as number) - 0.1;
}
return value;
} as NonNullable<ItemModule['onCalcOpposeStat']>,
};
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_12_맹덕신서',
rawName: '맹덕신서',
slot: 'book',
statName: 'intelligence',
statValue: 12,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,15 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_12_산해경',
rawName: '산해경',
slot: 'book',
statName: 'intelligence',
statValue: 12,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
extraInfo: '[전투] 상대의 계략을 10% 확률로 되돌림',
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_13_관자',
rawName: '관자',
slot: 'book',
statName: 'intelligence',
statValue: 13,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_13_병법24편',
rawName: '병법24편',
slot: 'book',
statName: 'intelligence',
statValue: 13,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_14_오자병법',
rawName: '오자병법',
slot: 'book',
statName: 'intelligence',
statValue: 14,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_14_한비자',
rawName: '한비자',
slot: 'book',
statName: 'intelligence',
statValue: 14,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_15_노자',
rawName: '노자',
slot: 'book',
statName: 'intelligence',
statValue: 15,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,14 @@
import { createStatItemModule } from './base.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = createStatItemModule({
key: 'che_서적_15_손자병법',
rawName: '손자병법',
slot: 'book',
statName: 'intelligence',
statValue: 15,
cost: 200,
buyable: false,
reqSecu: 0,
unique: true,
});
@@ -0,0 +1,29 @@
import type { GeneralActionContext } from '@sammo-ts/logic/triggers/general.js';
import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/types.js';
import type { WarActionContext } from '@sammo-ts/logic/war/actions.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_숙련_동작';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '동작',
name: '동작(숙련)',
info: '숙련 +20%',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
onCalcStat: function (
_context: GeneralActionContext | WarActionContext,
statName: GeneralStatName | WarStatName,
value: unknown
): unknown {
if (statName === ('addDex' as unknown as GeneralStatName)) {
return (value as number) * 1.2;
}
return value;
} as NonNullable<ItemModule['onCalcStat']>,
};
@@ -0,0 +1,122 @@
import { LogFormat } from '@sammo-ts/logic/logging/types.js';
import { TriggerPriority } from '@sammo-ts/logic/triggers/core.js';
import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js';
import { WarUnitGeneral, type WarUnit } from '@sammo-ts/logic/war/units.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_약탈_옥벽';
class CheTheftAttemptTrigger extends BaseWarUnitTrigger {
private readonly ratio: number;
private readonly theftRatio: number;
constructor(unit: WarUnit, raiseType: number, ratio: number, theftRatio: number) {
super(unit, TriggerPriority.Pre + 400, raiseType);
this.ratio = ratio;
this.theftRatio = theftRatio;
}
protected actionWar(
self: WarUnit,
oppose: WarUnit,
selfEnv: Record<string, unknown>,
_opposeEnv: Record<string, unknown>
): boolean {
if (!(self instanceof WarUnitGeneral)) {
return true;
}
if (self.getPhase() !== 0 && oppose.getPhase() !== 0) {
return true;
}
if (!(oppose instanceof WarUnitGeneral)) {
return true;
}
if (self.hasActivatedSkill('약탈')) {
return true;
}
if (self.hasActivatedSkill('약탈불가')) {
return true;
}
if (!self.rng.nextBool(this.ratio)) {
return true;
}
self.activateSkill('약탈');
selfEnv['theftRatio'] = this.theftRatio;
return true;
}
}
class CheTheftActivateTrigger extends BaseWarUnitTrigger {
constructor(unit: WarUnit, raiseType: number) {
super(unit, TriggerPriority.Post + 350, raiseType);
}
protected actionWar(
self: WarUnit,
oppose: WarUnit,
selfEnv: Record<string, unknown>,
_opposeEnv: Record<string, unknown>
): boolean {
if (!self.hasActivatedSkill('약탈')) {
return true;
}
if (selfEnv['약탈발동']) {
return true;
}
selfEnv['약탈발동'] = true;
if (!(self instanceof WarUnitGeneral) || !(oppose instanceof WarUnitGeneral)) {
return true;
}
const theftRatio = (selfEnv['theftRatio'] as number) ?? 0;
const selfGeneral = self.getGeneral();
const opposeGeneral = oppose.getGeneral();
const theftGold = Math.floor(opposeGeneral.gold * theftRatio);
const theftRice = Math.floor(opposeGeneral.rice * theftRatio);
opposeGeneral.gold = Math.max(0, opposeGeneral.gold - theftGold);
opposeGeneral.rice = Math.max(0, opposeGeneral.rice - theftRice);
selfGeneral.gold += theftGold;
selfGeneral.rice += theftRice;
self.getLogger().pushGeneralActionLog('상대를 <C>약탈</>했다!', LogFormat.PLAIN);
self.getLogger().pushGeneralBattleDetailLog(
`상대에게서 금 ${theftGold.toLocaleString()}, 쌀 ${theftRice.toLocaleString()} 만큼을 <C>약탈</>했다!`,
LogFormat.PLAIN
);
oppose.getLogger().pushGeneralActionLog('상대에게 <R>약탈</>당했다!', LogFormat.PLAIN);
oppose
.getLogger()
.pushGeneralBattleDetailLog(
`상대에게 금 ${theftGold.toLocaleString()}, 쌀 ${theftRice.toLocaleString()} 만큼을 <R>약탈</>당했다!`,
LogFormat.PLAIN
);
this.processConsumableItem();
return true;
}
}
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '옥벽',
name: '옥벽(약탈)',
info: '[전투] 새로운 상대와 전투 시 20% 확률로 상대 금, 쌀 10% 약탈',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
getBattlePhaseTriggerList: (context) => {
if (!context.unit) return null;
return new WarTriggerCaller(
new CheTheftAttemptTrigger(context.unit, BaseWarUnitTrigger.TYPE_ITEM, 0.2, 0.1),
new CheTheftActivateTrigger(context.unit, BaseWarUnitTrigger.TYPE_ITEM)
);
},
};
@@ -0,0 +1,19 @@
import { GeneralTriggerCaller } from '@sammo-ts/logic/triggers/general.js';
import { CheUisulCityHealTrigger } from '@sammo-ts/logic/triggers/generalTriggers/che_도시치료.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = {
key: 'che_의술_상한잡병론',
rawName: '상한잡병론',
name: '상한잡병론(의술)',
info: '[의술] 매달 도시의 부상병을 치료. 치료 효율 50% 향상',
slot: 'book',
cost: 500,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
getPreTurnExecuteTriggerList: (context) => {
return new GeneralTriggerCaller(new CheUisulCityHealTrigger(context.general, 1.5));
},
};
@@ -0,0 +1,19 @@
import { GeneralTriggerCaller } from '@sammo-ts/logic/triggers/general.js';
import { CheUisulCityHealTrigger } from '@sammo-ts/logic/triggers/generalTriggers/che_도시치료.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = {
key: 'che_의술_정력견혈산',
rawName: '정력견혈산',
name: '정력견혈산(의술)',
info: '[의술] 매달 도시의 부상병을 치료. 치료 효율 100% 향상',
slot: 'book',
cost: 500,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
getPreTurnExecuteTriggerList: (context) => {
return new GeneralTriggerCaller(new CheUisulCityHealTrigger(context.general, 2));
},
};
@@ -0,0 +1,19 @@
import { GeneralTriggerCaller } from '@sammo-ts/logic/triggers/general.js';
import { CheUisulCityHealTrigger } from '@sammo-ts/logic/triggers/generalTriggers/che_도시치료.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = {
key: 'che_의술_청낭서',
rawName: '청낭서',
name: '청낭서(의술)',
info: '[의술] 매달 도시의 부상병을 치료. 치료 효율 50% 향상',
slot: 'book',
cost: 500,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
getPreTurnExecuteTriggerList: (context) => {
return new GeneralTriggerCaller(new CheUisulCityHealTrigger(context.general, 1.5));
},
};
@@ -0,0 +1,19 @@
import { GeneralTriggerCaller } from '@sammo-ts/logic/triggers/general.js';
import { CheUisulCityHealTrigger } from '@sammo-ts/logic/triggers/generalTriggers/che_도시치료.js';
import type { ItemModule } from './types.js';
export const itemModule: ItemModule = {
key: 'che_의술_태평청령',
rawName: '태평청령',
name: '태평청령(의술)',
info: '[의술] 매달 도시의 부상병을 치료. 치료 효율 50% 향상',
slot: 'book',
cost: 500,
buyable: false,
consumable: false,
reqSecu: 0,
unique: false,
getPreTurnExecuteTriggerList: (context) => {
return new GeneralTriggerCaller(new CheUisulCityHealTrigger(context.general, 1.5));
},
};
@@ -0,0 +1,28 @@
import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js';
import { CheSnipingActivateTrigger, CheSnipingAttemptTrigger } from '@sammo-ts/logic/war/triggers/che_저격.js';
import { BaseWarUnitTrigger } from '@sammo-ts/logic/war/triggers.js';
import type { ItemModule } from './types.js';
const RAISE_TYPE = BaseWarUnitTrigger.TYPE_ITEM + BaseWarUnitTrigger.TYPE_DEDUP_TYPE_BASE * 304;
export const itemModule: ItemModule = {
key: 'che_저격_매화수전',
rawName: '매화수전',
name: '매화수전(저격)',
info: '[전투] 계략 시도 단계에서 저격 확률 50%',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: true,
getBattlePhaseTriggerList: (context) => {
if (!context.unit) {
return null;
}
return new WarTriggerCaller(
new CheSnipingAttemptTrigger(context.unit, RAISE_TYPE, 0.5, 20, 40),
new CheSnipingActivateTrigger(context.unit, RAISE_TYPE)
);
},
};
@@ -0,0 +1,28 @@
import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js';
import { CheSnipingActivateTrigger, CheSnipingAttemptTrigger } from '@sammo-ts/logic/war/triggers/che_저격.js';
import { BaseWarUnitTrigger } from '@sammo-ts/logic/war/triggers.js';
import type { ItemModule } from './types.js';
const RAISE_TYPE = BaseWarUnitTrigger.TYPE_ITEM + BaseWarUnitTrigger.TYPE_DEDUP_TYPE_BASE * 305;
export const itemModule: ItemModule = {
key: 'che_저격_비도',
rawName: '비도',
name: '비도(저격)',
info: '[전투] 계략 시도 단계에서 저격 확률 50%',
slot: 'item',
cost: 200,
buyable: false,
consumable: false,
reqSecu: 0,
unique: true,
getBattlePhaseTriggerList: (context) => {
if (!context.unit) {
return null;
}
return new WarTriggerCaller(
new CheSnipingAttemptTrigger(context.unit, RAISE_TYPE, 0.5, 20, 40),
new CheSnipingActivateTrigger(context.unit, RAISE_TYPE)
);
},
};
@@ -0,0 +1,25 @@
import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js';
import { CheSnipingAttemptTrigger, CheSnipingActivateTrigger } from '@sammo-ts/logic/war/triggers/che_저격.js';
import type { ItemModule } from './types.js';
const ITEM_KEY = 'che_저격_수극';
export const itemModule: ItemModule = {
key: ITEM_KEY,
rawName: '수극',
name: '수극(저격)',
info: '[전투] 전투 개시 시 저격. 1회용',
slot: 'item',
cost: 1000,
buyable: true,
consumable: true,
reqSecu: 1000,
unique: false,
getBattlePhaseTriggerList: (context) => {
if (!context.unit) return null;
return new WarTriggerCaller(
new CheSnipingAttemptTrigger(context.unit, BaseWarUnitTrigger.TYPE_CONSUMABLE_ITEM, 1, 20, 40),
new CheSnipingActivateTrigger(context.unit, BaseWarUnitTrigger.TYPE_CONSUMABLE_ITEM)
);
},
};

Some files were not shown because too many files have changed in this diff Show More