diff --git a/packages/logic/src/items/che_격노_구정신단경.ts b/packages/logic/src/items/che_격노_구정신단경.ts index a746a74..8f94214 100644 --- a/packages/logic/src/items/che_격노_구정신단경.ts +++ b/packages/logic/src/items/che_격노_구정신단경.ts @@ -1,78 +1,9 @@ -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 { che_격노발동, che_격노시도 } from '@sammo-ts/logic/war/triggers/che_격노.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, - _opposeEnv: Record - ): 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, - _opposeEnv: Record - ): boolean { - if (!self.hasActivatedSkill('격노')) { - return true; - } - - const targetAct = oppose.hasActivatedSkill('필살') ? '필살 공격' : '회피 시도'; - const isJinno = self.hasActivatedSkill('진노'); - const reaction = isJinno ? '진노' : '격노'; - - self.getLogger().pushGeneralBattleDetailLog(`상대의 ${targetAct}에 ${reaction}했다!`, LogFormat.PLAIN); - oppose - .getLogger() - .pushGeneralBattleDetailLog(`${targetAct}에 상대가 ${reaction}했다!`, LogFormat.PLAIN); - - if (isJinno) { - self.addBonusPhase(1); - } - self.multiplyWarPowerMultiply(self.criticalDamage()); - return true; - } -} - export const itemModule: ItemModule = { key: ITEM_KEY, rawName: '구정신단경', @@ -91,8 +22,8 @@ export const itemModule: ItemModule = { getBattlePhaseTriggerList: (context) => { if (!context.unit) return null; return new WarTriggerCaller( - new CheRageAttemptTrigger(context.unit, BaseWarUnitTrigger.TYPE_ITEM), - new CheRageActivateTrigger(context.unit, BaseWarUnitTrigger.TYPE_ITEM) + new che_격노시도(context.unit, BaseWarUnitTrigger.TYPE_ITEM), + new che_격노발동(context.unit, BaseWarUnitTrigger.TYPE_ITEM) ); }, }; diff --git a/packages/logic/src/items/che_명마_07_백마.ts b/packages/logic/src/items/che_명마_07_백마.ts index 71bcb15..89e31ba 100644 --- a/packages/logic/src/items/che_명마_07_백마.ts +++ b/packages/logic/src/items/che_명마_07_백마.ts @@ -1,5 +1,5 @@ import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import { CheRetreatNoWoundTrigger } from '@sammo-ts/logic/war/triggers/che_퇴각부상무효.js'; +import { che_퇴각부상무효 } from '@sammo-ts/logic/war/triggers/che_퇴각부상무효.js'; import { createStatItemModule } from './base.js'; import type { ItemModule } from './types.js'; @@ -22,6 +22,6 @@ export const itemModule: ItemModule = { if (!context.unit) { return null; } - return new WarTriggerCaller(new CheRetreatNoWoundTrigger(context.unit)); + return new WarTriggerCaller(new che_퇴각부상무효(context.unit)); }, }; diff --git a/packages/logic/src/items/che_명마_12_사륜거.ts b/packages/logic/src/items/che_명마_12_사륜거.ts index f687382..99a2bcf 100644 --- a/packages/logic/src/items/che_명마_12_사륜거.ts +++ b/packages/logic/src/items/che_명마_12_사륜거.ts @@ -1,5 +1,5 @@ import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import { CheRetreatNoWoundTrigger } from '@sammo-ts/logic/war/triggers/che_퇴각부상무효.js'; +import { che_퇴각부상무효 } from '@sammo-ts/logic/war/triggers/che_퇴각부상무효.js'; import { createStatItemModule } from './base.js'; import type { ItemModule } from './types.js'; @@ -22,6 +22,6 @@ export const itemModule: ItemModule = { if (!context.unit) { return null; } - return new WarTriggerCaller(new CheRetreatNoWoundTrigger(context.unit)); + return new WarTriggerCaller(new che_퇴각부상무효(context.unit)); }, }; diff --git a/packages/logic/src/items/che_무기_02_단궁.ts b/packages/logic/src/items/che_무기_02_단궁.ts index d20a107..d2ea567 100644 --- a/packages/logic/src/items/che_무기_02_단궁.ts +++ b/packages/logic/src/items/che_무기_02_단궁.ts @@ -1,5 +1,5 @@ import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import { CheSnipingActivateTrigger, CheSnipingAttemptTrigger } from '@sammo-ts/logic/war/triggers/che_저격.js'; +import { che_저격발동, che_저격시도 } from '@sammo-ts/logic/war/triggers/che_저격.js'; import { createStatItemModule } from './base.js'; import type { ItemModule } from './types.js'; @@ -24,8 +24,8 @@ export const itemModule: ItemModule = { return null; } return new WarTriggerCaller( - new CheSnipingAttemptTrigger(context.unit, raiseType, 0.01, 10, 30), - new CheSnipingActivateTrigger(context.unit, raiseType) + new che_저격시도(context.unit, raiseType, 0.01, 10, 30), + new che_저격발동(context.unit, raiseType) ); }, }; diff --git a/packages/logic/src/items/che_무기_09_동호비궁.ts b/packages/logic/src/items/che_무기_09_동호비궁.ts index a3b1d4f..e9c70fa 100644 --- a/packages/logic/src/items/che_무기_09_동호비궁.ts +++ b/packages/logic/src/items/che_무기_09_동호비궁.ts @@ -1,5 +1,5 @@ import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import { CheSnipingActivateTrigger, CheSnipingAttemptTrigger } from '@sammo-ts/logic/war/triggers/che_저격.js'; +import { che_저격발동, che_저격시도 } from '@sammo-ts/logic/war/triggers/che_저격.js'; import { createStatItemModule } from './base.js'; import type { ItemModule } from './types.js'; @@ -25,8 +25,8 @@ export const itemModule: ItemModule = { return null; } return new WarTriggerCaller( - new CheSnipingAttemptTrigger(context.unit, raiseType, 0.2, 20, 40, 20), - new CheSnipingActivateTrigger(context.unit, raiseType) + new che_저격시도(context.unit, raiseType, 0.2, 20, 40, 20), + new che_저격발동(context.unit, raiseType) ); }, }; diff --git a/packages/logic/src/items/che_부적_태현청생부.ts b/packages/logic/src/items/che_부적_태현청생부.ts index 21863e6..80261ab 100644 --- a/packages/logic/src/items/che_부적_태현청생부.ts +++ b/packages/logic/src/items/che_부적_태현청생부.ts @@ -1,23 +1,12 @@ 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 { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; +import { che_부적 } from '@sammo-ts/logic/war/triggers/che_부적.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: '태현청생부', @@ -41,6 +30,6 @@ export const itemModule: ItemModule = { } as NonNullable, getBattlePhaseTriggerList: (context) => { if (!context.unit) return null; - return new WarTriggerCaller(new CheAmuletTrigger(context.unit)); + return new WarTriggerCaller(new che_부적(context.unit)); }, }; diff --git a/packages/logic/src/items/che_사기_탁주.ts b/packages/logic/src/items/che_사기_탁주.ts index 14fabdf..12b60db 100644 --- a/packages/logic/src/items/che_사기_탁주.ts +++ b/packages/logic/src/items/che_사기_탁주.ts @@ -1,24 +1,9 @@ import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import type { WarUnit } from '@sammo-ts/logic/war/units.js'; +import { che_사기 } from '@sammo-ts/logic/war/triggers/che_사기.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: '탁주', @@ -33,7 +18,7 @@ export const itemModule: ItemModule = { getBattleInitTriggerList: (context) => { if (!context.unit) return null; return new WarTriggerCaller( - new CheAtmosIncreaseTrigger(context.unit, BaseWarUnitTrigger.TYPE_CONSUMABLE_ITEM, 30) + new che_사기(context.unit, BaseWarUnitTrigger.TYPE_CONSUMABLE_ITEM, 30) ); }, }; diff --git a/packages/logic/src/items/che_약탈_옥벽.ts b/packages/logic/src/items/che_약탈_옥벽.ts index 58ae82d..e865f21 100644 --- a/packages/logic/src/items/che_약탈_옥벽.ts +++ b/packages/logic/src/items/che_약탈_옥벽.ts @@ -1,106 +1,9 @@ -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 { che_약탈발동, che_약탈시도 } from '@sammo-ts/logic/war/triggers/che_약탈.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, - _opposeEnv: Record - ): 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, - _opposeEnv: Record - ): 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('상대를 약탈했다!', LogFormat.PLAIN); - self.getLogger().pushGeneralBattleDetailLog( - `상대에게서 금 ${theftGold.toLocaleString()}, 쌀 ${theftRice.toLocaleString()} 만큼을 약탈했다!`, - LogFormat.PLAIN - ); - oppose.getLogger().pushGeneralActionLog('상대에게 약탈당했다!', LogFormat.PLAIN); - oppose - .getLogger() - .pushGeneralBattleDetailLog( - `상대에게 금 ${theftGold.toLocaleString()}, 쌀 ${theftRice.toLocaleString()} 만큼을 약탈당했다!`, - LogFormat.PLAIN - ); - - this.processConsumableItem(); - return true; - } -} - export const itemModule: ItemModule = { key: ITEM_KEY, rawName: '옥벽', @@ -115,8 +18,8 @@ export const itemModule: ItemModule = { 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) + new che_약탈시도(context.unit, BaseWarUnitTrigger.TYPE_ITEM, 0.2, 0.1), + new che_약탈발동(context.unit, BaseWarUnitTrigger.TYPE_ITEM) ); }, }; diff --git a/packages/logic/src/items/che_저격_매화수전.ts b/packages/logic/src/items/che_저격_매화수전.ts index 660fad2..f1047ab 100644 --- a/packages/logic/src/items/che_저격_매화수전.ts +++ b/packages/logic/src/items/che_저격_매화수전.ts @@ -1,5 +1,5 @@ import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import { CheSnipingActivateTrigger, CheSnipingAttemptTrigger } from '@sammo-ts/logic/war/triggers/che_저격.js'; +import { che_저격발동, che_저격시도 } from '@sammo-ts/logic/war/triggers/che_저격.js'; import { BaseWarUnitTrigger } from '@sammo-ts/logic/war/triggers.js'; import type { ItemModule } from './types.js'; @@ -21,8 +21,8 @@ export const itemModule: ItemModule = { return null; } return new WarTriggerCaller( - new CheSnipingAttemptTrigger(context.unit, RAISE_TYPE, 0.5, 20, 40), - new CheSnipingActivateTrigger(context.unit, RAISE_TYPE) + new che_저격시도(context.unit, RAISE_TYPE, 0.5, 20, 40), + new che_저격발동(context.unit, RAISE_TYPE) ); }, }; diff --git a/packages/logic/src/items/che_저격_비도.ts b/packages/logic/src/items/che_저격_비도.ts index a8ac303..8c9d044 100644 --- a/packages/logic/src/items/che_저격_비도.ts +++ b/packages/logic/src/items/che_저격_비도.ts @@ -1,5 +1,5 @@ import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import { CheSnipingActivateTrigger, CheSnipingAttemptTrigger } from '@sammo-ts/logic/war/triggers/che_저격.js'; +import { che_저격발동, che_저격시도 } from '@sammo-ts/logic/war/triggers/che_저격.js'; import { BaseWarUnitTrigger } from '@sammo-ts/logic/war/triggers.js'; import type { ItemModule } from './types.js'; @@ -21,8 +21,8 @@ export const itemModule: ItemModule = { return null; } return new WarTriggerCaller( - new CheSnipingAttemptTrigger(context.unit, RAISE_TYPE, 0.5, 20, 40), - new CheSnipingActivateTrigger(context.unit, RAISE_TYPE) + new che_저격시도(context.unit, RAISE_TYPE, 0.5, 20, 40), + new che_저격발동(context.unit, RAISE_TYPE) ); }, }; diff --git a/packages/logic/src/items/che_저격_수극.ts b/packages/logic/src/items/che_저격_수극.ts index 59a7cd5..80530d7 100644 --- a/packages/logic/src/items/che_저격_수극.ts +++ b/packages/logic/src/items/che_저격_수극.ts @@ -1,5 +1,5 @@ import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import { CheSnipingAttemptTrigger, CheSnipingActivateTrigger } from '@sammo-ts/logic/war/triggers/che_저격.js'; +import { che_저격시도, che_저격발동 } from '@sammo-ts/logic/war/triggers/che_저격.js'; import type { ItemModule } from './types.js'; const ITEM_KEY = 'che_저격_수극'; @@ -18,8 +18,8 @@ export const itemModule: ItemModule = { 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) + new che_저격시도(context.unit, BaseWarUnitTrigger.TYPE_CONSUMABLE_ITEM, 1, 20, 40), + new che_저격발동(context.unit, BaseWarUnitTrigger.TYPE_CONSUMABLE_ITEM) ); }, }; diff --git a/packages/logic/src/items/che_저지_삼황내문.ts b/packages/logic/src/items/che_저지_삼황내문.ts index 81bab1c..934046d 100644 --- a/packages/logic/src/items/che_저지_삼황내문.ts +++ b/packages/logic/src/items/che_저지_삼황내문.ts @@ -1,59 +1,9 @@ -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 { che_저지, che_저지_시도 } from '@sammo-ts/logic/war/triggers/che_저지.js'; +import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; import type { ItemModule } from './types.js'; const ITEM_KEY = 'che_저지_삼황내문'; -class CheHaltTrigger extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, TriggerPriority.Post); - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - selfEnv: Record, - _opposeEnv: Record - ): boolean { - if (!self.hasActivatedSkill('저지')) { - return true; - } - - if (selfEnv['저지발동']) { - return true; - } - selfEnv['저지발동'] = true; - - self.addPhase(-1); - oppose.addPhase(-1); - if (self.getPhase() < self.getMaxPhase()) { - oppose.addBonusPhase(-1); - } - - self.getLogger().pushGeneralBattleDetailLog('상대를 저지했다!', LogFormat.PLAIN); - oppose.getLogger().pushGeneralBattleDetailLog('저지당했다!', LogFormat.PLAIN); - - const calcDamage = oppose.getWarPower() * 0.9; - if (self instanceof WarUnitGeneral) { - self.addDex(oppose.getCrewType(), oppose.getWarPower() * 0.9); - self.addDex(self.getCrewType(), calcDamage); - - self.addLevelExp(calcDamage / 50); - let rice = self.calcRiceConsumption(calcDamage); - rice *= 0.25; - const general = self.getGeneral(); - general.rice = Math.max(0, general.rice - rice); - } - - self.setWarPowerMultiply(0); - oppose.setWarPowerMultiply(0); - - return false; - } -} - export const itemModule: ItemModule = { key: ITEM_KEY, rawName: '삼황내문', @@ -83,16 +33,8 @@ export const itemModule: ItemModule = { } return new WarTriggerCaller( - new (class extends BaseWarUnitTrigger { - constructor(u: WarUnit) { - super(u, TriggerPriority.Pre); - } - protected actionWar(u: WarUnit): boolean { - u.activateSkill('특수', '저지'); - return true; - } - })(unit), - new CheHaltTrigger(unit) + new che_저지_시도(unit), + new che_저지(unit) ); }, }; diff --git a/packages/logic/src/items/che_진압_박혁론.ts b/packages/logic/src/items/che_진압_박혁론.ts index 4ae4a0b..749291e 100644 --- a/packages/logic/src/items/che_진압_박혁론.ts +++ b/packages/logic/src/items/che_진압_박혁론.ts @@ -1,20 +1,10 @@ -import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import type { WarUnit } from '@sammo-ts/logic/war/units.js'; +import { che_진압 } from '@sammo-ts/logic/war/triggers/che_진압.js'; + +import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; import type { ItemModule } from './types.js'; const ITEM_KEY = 'che_진압_박혁론'; -class CheSuppressTrigger extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, 0); // Priority 0 or matching legacy - } - - protected actionWar(self: WarUnit): boolean { - self.activateSkill('반계불가', '격노불가'); - return true; - } -} - export const itemModule: ItemModule = { key: ITEM_KEY, rawName: '박혁론', @@ -28,6 +18,6 @@ export const itemModule: ItemModule = { unique: false, getBattlePhaseTriggerList: (context) => { if (!context.unit) return null; - return new WarTriggerCaller(new CheSuppressTrigger(context.unit)); + return new WarTriggerCaller(new che_진압(context.unit)); }, }; diff --git a/packages/logic/src/items/che_훈련_청주.ts b/packages/logic/src/items/che_훈련_청주.ts index 363eee1..09cfd13 100644 --- a/packages/logic/src/items/che_훈련_청주.ts +++ b/packages/logic/src/items/che_훈련_청주.ts @@ -1,24 +1,9 @@ import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import type { WarUnit } from '@sammo-ts/logic/war/units.js'; +import { che_훈련 } from '@sammo-ts/logic/war/triggers/che_훈련.js'; import type { ItemModule } from './types.js'; const ITEM_KEY = 'che_훈련_청주'; -class CheTrainIncreaseTrigger 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.addTrain(this.amount); - this.processConsumableItem(); - return true; - } -} - export const itemModule: ItemModule = { key: ITEM_KEY, rawName: '청주', @@ -33,7 +18,7 @@ export const itemModule: ItemModule = { getBattleInitTriggerList: (context) => { if (!context.unit) return null; return new WarTriggerCaller( - new CheTrainIncreaseTrigger(context.unit, BaseWarUnitTrigger.TYPE_CONSUMABLE_ITEM, 40) + new che_훈련(context.unit, BaseWarUnitTrigger.TYPE_CONSUMABLE_ITEM, 40) ); }, }; diff --git a/packages/logic/src/triggers/special/war/che_격노.ts b/packages/logic/src/triggers/special/war/che_격노.ts index 7401959..472c859 100644 --- a/packages/logic/src/triggers/special/war/che_격노.ts +++ b/packages/logic/src/triggers/special/war/che_격노.ts @@ -3,77 +3,8 @@ import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/type import type { WarActionContext } from '@sammo-ts/logic/war/actions.js'; import type { TraitModule } from '@sammo-ts/logic/triggers/special/types.js'; import { TraitRequirement, TraitWeightType } from '../requirements.js'; -import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import type { WarUnit } from '@sammo-ts/logic/war/units.js'; -import { LogFormat } from '@sammo-ts/logic/logging/types.js'; - -class che_격노시도 extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, 30400); - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - _selfEnv: Record, - _opposeEnv: Record - ): 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(1 / 2)) { - self.activateSkill('진노'); - } - } else if (self.rng.nextBool(1 / 4)) { - self.activateSkill('격노'); - oppose.deactivateSkill('회피'); - if (self.isAttacker() && self.rng.nextBool(1 / 2)) { - self.activateSkill('진노'); - } - } - return true; - } -} - -class che_격노발동 extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, 40600); - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - _selfEnv: Record, - _opposeEnv: Record - ): boolean { - if (!self.hasActivatedSkill('격노')) { - return true; - } - - const targetAct = oppose.hasActivatedSkill('필살') ? '필살 공격' : '회피 시도'; - const is진노 = self.hasActivatedSkill('진노'); - const reaction = is진노 ? '진노' : '격노'; - - self.getLogger().pushGeneralBattleDetailLog(`상대의 ${targetAct}에 ${reaction}했다!`, LogFormat.PLAIN); - oppose - .getLogger() - .pushGeneralBattleDetailLog(`${targetAct}에 상대가 ${reaction}했다!`, LogFormat.PLAIN); - - if (is진노) { - self.addBonusPhase(1); - } - self.multiplyWarPowerMultiply(self.criticalDamage()); - - return true; - } -} +import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; +import { che_격노발동, che_격노시도 } from '@sammo-ts/logic/war/triggers/che_격노.js'; function onCalcStat(context: GeneralActionContext, statName: GeneralStatName, value: number, aux?: unknown): number; function onCalcStat( diff --git a/packages/logic/src/triggers/special/war/che_견고.ts b/packages/logic/src/triggers/special/war/che_견고.ts index 042df7d..5daf301 100644 --- a/packages/logic/src/triggers/special/war/che_견고.ts +++ b/packages/logic/src/triggers/special/war/che_견고.ts @@ -3,24 +3,8 @@ import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/type import type { WarActionContext } from '@sammo-ts/logic/war/actions.js'; import type { TraitModule } from '@sammo-ts/logic/triggers/special/types.js'; import { TraitRequirement, TraitWeightType } from '../requirements.js'; -import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import type { WarUnit } from '@sammo-ts/logic/war/units.js'; - -class che_부상무효 extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, 10200); - } - - protected actionWar( - self: WarUnit, - _oppose: WarUnit, - _selfEnv: Record, - _opposeEnv: Record - ): boolean { - self.activateSkill('부상무효'); - return true; - } -} +import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; +import { che_부상무효 } from '@sammo-ts/logic/war/triggers/che_견고.js'; function onCalcStat(context: GeneralActionContext, statName: GeneralStatName, value: number, aux?: unknown): number; function onCalcStat( diff --git a/packages/logic/src/triggers/special/war/che_돌격.ts b/packages/logic/src/triggers/special/war/che_돌격.ts index d5b59b2..6ccb864 100644 --- a/packages/logic/src/triggers/special/war/che_돌격.ts +++ b/packages/logic/src/triggers/special/war/che_돌격.ts @@ -3,40 +3,8 @@ 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 { TraitModule } from '@sammo-ts/logic/triggers/special/types.js'; -import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import type { WarUnit } from '@sammo-ts/logic/war/units.js'; - -class che_돌격지속 extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, 40900); - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - _selfEnv: Record, - _opposeEnv: Record - ): boolean { - if (oppose.constructor.name === 'WarUnitCity') { - return true; - } - if (!self.isAttacker()) { - return true; - } - const attackCoef = self.getCrewType().getAttackCoef(oppose.getCrewType()); - if (attackCoef < 1) { - if (oppose.hasActivatedSkill('선제') && self.getPhase() >= self.getMaxPhase() - 2) { - self.addBonusPhase(-1); - } - return true; - } - if (self.getPhase() < self.getMaxPhase() - 1) { - return true; - } - self.addBonusPhase(1); - return true; - } -} +import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; +import { che_돌격지속 } from '@sammo-ts/logic/war/triggers/che_돌격.js'; function onCalcStat(context: GeneralActionContext, statName: GeneralStatName, value: number, aux?: unknown): number; function onCalcStat( diff --git a/packages/logic/src/triggers/special/war/che_반계.ts b/packages/logic/src/triggers/special/war/che_반계.ts index c384b9c..dfd8095 100644 --- a/packages/logic/src/triggers/special/war/che_반계.ts +++ b/packages/logic/src/triggers/special/war/che_반계.ts @@ -3,75 +3,8 @@ import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/type import type { WarActionContext } from '@sammo-ts/logic/war/actions.js'; import type { TraitModule } from '@sammo-ts/logic/triggers/special/types.js'; import { TraitRequirement, TraitWeightType } from '../requirements.js'; -import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import type { WarUnit } from '@sammo-ts/logic/war/units.js'; -import { LogFormat } from '@sammo-ts/logic/logging/types.js'; - -class che_반계시도 extends BaseWarUnitTrigger { - private readonly prob: number; - - constructor(unit: WarUnit, prob = 0.4) { - super(unit, 30300); - this.prob = prob; - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - _selfEnv: Record, - _opposeEnv: Record - ): boolean { - if (!oppose.hasActivatedSkill('계략')) { - return true; - } - if (self.hasActivatedSkill('반계불가')) { - return true; - } - - if (!self.rng.nextBool(this.prob)) { - return true; - } - - self.activateSkill('반계'); - oppose.deactivateSkill('계략'); - - return true; - } -} - -class che_반계발동 extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, 40250); - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - _selfEnv: Record, - opposeEnv: Record - ): boolean { - if (!self.hasActivatedSkill('반계')) { - return true; - } - - const magicData = opposeEnv.magic as [string, number] | undefined; - if (!magicData) { - return true; - } - - const [opposeMagic, damage] = magicData; - - self.getLogger().pushGeneralBattleDetailLog( - `반계로 상대의 ${opposeMagic}을 되돌렸다!`, - LogFormat.PLAIN - ); - oppose.getLogger().pushGeneralBattleDetailLog(`${opposeMagic}을 역으로 당했다!`, LogFormat.PLAIN); - - self.multiplyWarPowerMultiply(damage); - - return true; - } -} +import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; +import { che_반계발동, che_반계시도 } from '@sammo-ts/logic/war/triggers/che_반계.js'; function onCalcStat(context: GeneralActionContext, statName: GeneralStatName, value: number, aux?: unknown): number; function onCalcStat( diff --git a/packages/logic/src/triggers/special/war/che_위압.ts b/packages/logic/src/triggers/special/war/che_위압.ts index 1d7e1e4..824c4a9 100644 --- a/packages/logic/src/triggers/special/war/che_위압.ts +++ b/packages/logic/src/triggers/special/war/che_위압.ts @@ -3,64 +3,8 @@ import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/type import type { WarActionContext } from '@sammo-ts/logic/war/actions.js'; import type { TraitModule } from '@sammo-ts/logic/triggers/special/types.js'; import { TraitRequirement, TraitWeightType } from '../requirements.js'; -import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import type { WarUnit } from '@sammo-ts/logic/war/units.js'; -import { LogFormat } from '@sammo-ts/logic/logging/types.js'; - -type AtmosUnit = WarUnit & { addAtmos: (amount: number) => void }; - -const canAddAtmos = (unit: WarUnit): unit is AtmosUnit => - 'addAtmos' in unit && typeof (unit as { addAtmos?: unknown }).addAtmos === 'function'; - -class che_위압시도 extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, 10100); - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - _selfEnv: Record, - _opposeEnv: Record - ): boolean { - if (self.getPhase() !== 0 && oppose.getPhase() !== 0) { - return true; - } - if (self.hasActivatedSkill('위압불가')) { - return true; - } - - self.activateSkill('위압'); - oppose.activateSkill('회피불가', '필살불가', '계략불가'); - return true; - } -} - -class che_위압발동 extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, 40700); - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - _selfEnv: Record, - _opposeEnv: Record - ): boolean { - if (!self.hasActivatedSkill('위압')) { - return true; - } - - oppose.getLogger().pushGeneralBattleDetailLog('상대에게 위압받았다!', LogFormat.PLAIN); - self.getLogger().pushGeneralBattleDetailLog('상대에게 위압을 줬다!', LogFormat.PLAIN); - oppose.setWarPowerMultiply(0); - if (canAddAtmos(oppose)) { - oppose.addAtmos(-5); - } - - return true; - } -} +import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; +import { che_위압발동, che_위압시도 } from '@sammo-ts/logic/war/triggers/che_위압.js'; function onCalcStat(context: GeneralActionContext, statName: GeneralStatName, value: number, aux?: unknown): number; function onCalcStat( diff --git a/packages/logic/src/triggers/special/war/che_저격.ts b/packages/logic/src/triggers/special/war/che_저격.ts index eeb240b..463cd49 100644 --- a/packages/logic/src/triggers/special/war/che_저격.ts +++ b/packages/logic/src/triggers/special/war/che_저격.ts @@ -4,101 +4,7 @@ import type { WarActionContext } from '@sammo-ts/logic/war/actions.js'; import type { TraitModule } from '@sammo-ts/logic/triggers/special/types.js'; import { TraitRequirement, TraitWeightType } from '../requirements.js'; import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import type { WarUnit } from '@sammo-ts/logic/war/units.js'; -import { LogFormat } from '@sammo-ts/logic/logging/types.js'; - -type AtmosUnit = WarUnit & { addAtmos: (amount: number) => void }; - -const canAddAtmos = (unit: WarUnit): unit is AtmosUnit => - 'addAtmos' in unit && typeof (unit as { addAtmos?: unknown }).addAtmos === 'function'; - -class che_저격시도 extends BaseWarUnitTrigger { - private readonly ratio: number; - private readonly woundMin: number; - private readonly woundMax: number; - private readonly addAtmos: number; - - constructor(unit: WarUnit, ratio: number, woundMin: number, woundMax: number, addAtmos = 20) { - super(unit, 20100); - this.ratio = ratio; - this.woundMin = woundMin; - this.woundMax = woundMax; - this.addAtmos = addAtmos; - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - selfEnv: Record, - _opposeEnv: Record - ): boolean { - if (self.getPhase() !== 0 && oppose.getPhase() !== 0) { - return true; - } - if (oppose.getPhase() < 0) { - return true; - } - if (self.hasActivatedSkill('저격')) { - return true; - } - if (self.hasActivatedSkill('저격불가')) { - return true; - } - if (!self.rng.nextBool(this.ratio)) { - return true; - } - - self.activateSkill('저격'); - selfEnv['저격발동자'] = this.raiseType; - selfEnv['woundMin'] = this.woundMin; - selfEnv['woundMax'] = this.woundMax; - selfEnv['addAtmos'] = this.addAtmos; - - return true; - } -} - -class che_저격발동 extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, 40100); - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - selfEnv: Record, - _opposeEnv: Record - ): boolean { - if (!self.hasActivatedSkill('저격')) { - return true; - } - - if (((selfEnv['저격발동자'] as number) ?? -1) !== this.raiseType) { - return true; - } - - if ((selfEnv['저격발동'] as boolean) ?? false) { - return true; - } - selfEnv['저격발동'] = true; - - if (oppose.constructor.name === 'WarUnitGeneral') { - self.getLogger().pushGeneralActionLog('상대를 저격했다!', LogFormat.PLAIN); - self.getLogger().pushGeneralBattleDetailLog('상대를 저격했다!', LogFormat.PLAIN); - oppose.getLogger().pushGeneralActionLog('상대에게 저격당했다!', LogFormat.PLAIN); - oppose.getLogger().pushGeneralBattleDetailLog('상대에게 저격당했다!', LogFormat.PLAIN); - } else { - self.getLogger().pushGeneralActionLog('성벽 수비대장을 저격했다!', LogFormat.PLAIN); - self.getLogger().pushGeneralBattleDetailLog('성벽 수비대장을 저격했다!', LogFormat.PLAIN); - } - - if (canAddAtmos(self)) { - self.addAtmos(selfEnv['addAtmos'] as number); - } - - return true; - } -} +import { che_저격발동, che_저격시도 } from '@sammo-ts/logic/war/triggers/che_저격.js'; function onCalcStat(context: GeneralActionContext, statName: GeneralStatName, value: number, aux?: unknown): number; function onCalcStat( @@ -130,7 +36,10 @@ export const traitModule: TraitModule = { }, getBattlePhaseTriggerList: (_context) => { if (!_context.unit) return null; - return new WarTriggerCaller(new che_저격시도(_context.unit, 0.5, 20, 40, 20), new che_저격발동(_context.unit)); + return new WarTriggerCaller( + new che_저격시도(_context.unit, BaseWarUnitTrigger.TYPE_NONE, 0.5, 20, 40, 20), + new che_저격발동(_context.unit, BaseWarUnitTrigger.TYPE_NONE) + ); }, onCalcStat, }; diff --git a/packages/logic/src/triggers/special/war/che_필살.ts b/packages/logic/src/triggers/special/war/che_필살.ts index b93571b..f4a33e5 100644 --- a/packages/logic/src/triggers/special/war/che_필살.ts +++ b/packages/logic/src/triggers/special/war/che_필살.ts @@ -3,28 +3,8 @@ import type { GeneralStatName, WarStatName } from '@sammo-ts/logic/triggers/type import type { WarActionContext } from '@sammo-ts/logic/war/actions.js'; import type { TraitModule } from '@sammo-ts/logic/triggers/special/types.js'; import { TraitRequirement, TraitWeightType } from '../requirements.js'; -import { BaseWarUnitTrigger, WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; -import type { WarUnit } from '@sammo-ts/logic/war/units.js'; - -class che_필살강화_회피불가 extends BaseWarUnitTrigger { - constructor(unit: WarUnit) { - super(unit, 20150); - } - - protected actionWar( - self: WarUnit, - oppose: WarUnit, - _selfEnv: Record, - _opposeEnv: Record - ): boolean { - if (!self.hasActivatedSkill('필살')) { - return true; - } - - oppose.activateSkill('회피불가'); - return true; - } -} +import { WarTriggerCaller } from '@sammo-ts/logic/war/triggers.js'; +import { che_필살강화_회피불가 } from '@sammo-ts/logic/war/triggers/che_필살.js'; function onCalcStat(context: GeneralActionContext, statName: GeneralStatName, value: number, aux?: unknown): number; function onCalcStat( diff --git a/packages/logic/src/war/triggers/che_격노.ts b/packages/logic/src/war/triggers/che_격노.ts new file mode 100644 index 0000000..1975d56 --- /dev/null +++ b/packages/logic/src/war/triggers/che_격노.ts @@ -0,0 +1,72 @@ +import { LogFormat } from '@sammo-ts/logic/logging/types.js'; +import { TriggerPriority } from '@sammo-ts/logic/triggers/core.js'; +import { BaseWarUnitTrigger } from '@sammo-ts/logic/war/triggers.js'; +import type { WarUnit } from '@sammo-ts/logic/war/units.js'; + +export class che_격노시도 extends BaseWarUnitTrigger { + constructor(unit: WarUnit, raiseType: number = 0) { + super(unit, TriggerPriority.Pre + 300, raiseType); + } + + protected actionWar( + self: WarUnit, + oppose: WarUnit, + _selfEnv: Record, + _opposeEnv: Record + ): 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(1 / 2)) { + self.activateSkill('진노'); + } + } else if (self.rng.nextBool(1 / 4)) { + self.activateSkill('격노'); + oppose.deactivateSkill('회피'); + if (self.isAttacker() && self.rng.nextBool(1 / 2)) { + self.activateSkill('진노'); + } + } + return true; + } +} + +export class che_격노발동 extends BaseWarUnitTrigger { + constructor(unit: WarUnit, raiseType: number = 0) { + super(unit, TriggerPriority.Post + 450, raiseType); + } + + protected actionWar( + self: WarUnit, + oppose: WarUnit, + _selfEnv: Record, + _opposeEnv: Record + ): boolean { + if (!self.hasActivatedSkill('격노')) { + return true; + } + + const targetAct = oppose.hasActivatedSkill('필살') ? '필살 공격' : '회피 시도'; + const is진노 = self.hasActivatedSkill('진노'); + const reaction = is진노 ? '진노' : '격노'; + + self.getLogger().pushGeneralBattleDetailLog(`상대의 ${targetAct}에 ${reaction}했다!`, LogFormat.PLAIN); + oppose + .getLogger() + .pushGeneralBattleDetailLog(`${targetAct}에 상대가 ${reaction}했다!`, LogFormat.PLAIN); + + if (is진노) { + self.addBonusPhase(1); + } + self.multiplyWarPowerMultiply(self.criticalDamage()); + + return true; + } +} diff --git a/packages/logic/src/war/triggers/che_견고.ts b/packages/logic/src/war/triggers/che_견고.ts new file mode 100644 index 0000000..0062277 --- /dev/null +++ b/packages/logic/src/war/triggers/che_견고.ts @@ -0,0 +1,19 @@ +import { TriggerPriority } from '@sammo-ts/logic/triggers/core.js'; +import { BaseWarUnitTrigger } from '@sammo-ts/logic/war/triggers.js'; +import type { WarUnit } from '@sammo-ts/logic/war/units.js'; + +export class che_부상무효 extends BaseWarUnitTrigger { + constructor(unit: WarUnit) { + super(unit, TriggerPriority.Begin + 200); + } + + protected actionWar( + self: WarUnit, + _oppose: WarUnit, + _selfEnv: Record, + _opposeEnv: Record + ): boolean { + self.activateSkill('부상무효'); + return true; + } +} diff --git a/packages/logic/src/war/triggers/che_돌격.ts b/packages/logic/src/war/triggers/che_돌격.ts new file mode 100644 index 0000000..dc7f7d0 --- /dev/null +++ b/packages/logic/src/war/triggers/che_돌격.ts @@ -0,0 +1,36 @@ +import { TriggerPriority } from '@sammo-ts/logic/triggers/core.js'; +import { BaseWarUnitTrigger } from '@sammo-ts/logic/war/triggers.js'; +import type { WarUnit } from '@sammo-ts/logic/war/units.js'; + +export class che_돌격지속 extends BaseWarUnitTrigger { + constructor(unit: WarUnit) { + super(unit, TriggerPriority.Post + 900); + } + + protected actionWar( + self: WarUnit, + oppose: WarUnit, + _selfEnv: Record, + _opposeEnv: Record + ): boolean { + // WarUnitCity check + if (oppose.constructor.name === 'WarUnitCity') { + return true; + } + if (!self.isAttacker()) { + return true; + } + const attackCoef = self.getCrewType().getAttackCoef(oppose.getCrewType()); + if (attackCoef < 1) { + if (oppose.hasActivatedSkill('선제') && self.getPhase() >= self.getMaxPhase() - 2) { + self.addBonusPhase(-1); + } + return true; + } + if (self.getPhase() < self.getMaxPhase() - 1) { + return true; + } + self.addBonusPhase(1); + return true; + } +} diff --git a/packages/logic/src/war/triggers/che_반계.ts b/packages/logic/src/war/triggers/che_반계.ts new file mode 100644 index 0000000..6a1b244 --- /dev/null +++ b/packages/logic/src/war/triggers/che_반계.ts @@ -0,0 +1,70 @@ +import { LogFormat } from '@sammo-ts/logic/logging/types.js'; +import { TriggerPriority } from '@sammo-ts/logic/triggers/core.js'; +import { BaseWarUnitTrigger } from '@sammo-ts/logic/war/triggers.js'; +import type { WarUnit } from '@sammo-ts/logic/war/units.js'; + +export class che_반계시도 extends BaseWarUnitTrigger { + private readonly prob: number; + + constructor(unit: WarUnit, prob = 0.4) { + super(unit, TriggerPriority.Pre + 200); + this.prob = prob; + } + + protected actionWar( + self: WarUnit, + oppose: WarUnit, + _selfEnv: Record, + _opposeEnv: Record + ): boolean { + if (!oppose.hasActivatedSkill('계략')) { + return true; + } + if (self.hasActivatedSkill('반계불가')) { + return true; + } + + if (!self.rng.nextBool(this.prob)) { + return true; + } + + self.activateSkill('반계'); + oppose.deactivateSkill('계략'); + + return true; + } +} + +export class che_반계발동 extends BaseWarUnitTrigger { + constructor(unit: WarUnit) { + super(unit, TriggerPriority.Post + 150); + } + + protected actionWar( + self: WarUnit, + oppose: WarUnit, + _selfEnv: Record, + opposeEnv: Record + ): boolean { + if (!self.hasActivatedSkill('반계')) { + return true; + } + + const magicData = opposeEnv.magic as [string, number] | undefined; + if (!magicData) { + return true; + } + + const [opposeMagic, damage] = magicData; + + self.getLogger().pushGeneralBattleDetailLog( + `반계로 상대의 ${opposeMagic}을 되돌렸다!`, + LogFormat.PLAIN + ); + oppose.getLogger().pushGeneralBattleDetailLog(`${opposeMagic}을 역으로 당했다!`, LogFormat.PLAIN); + + self.multiplyWarPowerMultiply(damage); + + return true; + } +} diff --git a/packages/logic/src/war/triggers/che_부적.ts b/packages/logic/src/war/triggers/che_부적.ts new file mode 100644 index 0000000..663e1cf --- /dev/null +++ b/packages/logic/src/war/triggers/che_부적.ts @@ -0,0 +1,13 @@ +import { BaseWarUnitTrigger } from '../triggers.js'; +import type { WarUnit } from '../units.js'; + +export class che_부적 extends BaseWarUnitTrigger { + constructor(unit: WarUnit, raiseType: number = 0) { + super(unit, 0, raiseType); + } + + protected actionWar(self: WarUnit): boolean { + self.activateSkill('저격불가', '부상무효'); + return true; + } +} diff --git a/packages/logic/src/war/triggers/che_사기.ts b/packages/logic/src/war/triggers/che_사기.ts new file mode 100644 index 0000000..30b6cf9 --- /dev/null +++ b/packages/logic/src/war/triggers/che_사기.ts @@ -0,0 +1,17 @@ +import { BaseWarUnitTrigger } from '../triggers.js'; +import type { WarUnit } from '../units.js'; + +export class che_사기 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; + } +} diff --git a/packages/logic/src/war/triggers/che_약탈.ts b/packages/logic/src/war/triggers/che_약탈.ts new file mode 100644 index 0000000..b642dab --- /dev/null +++ b/packages/logic/src/war/triggers/che_약탈.ts @@ -0,0 +1,99 @@ +import { LogFormat } from '@sammo-ts/logic/logging/types.js'; +import { TriggerPriority } from '@sammo-ts/logic/triggers/core.js'; +import { BaseWarUnitTrigger } from '../triggers.js'; +import { WarUnitGeneral, type WarUnit } from '../units.js'; + +export class che_약탈시도 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, + _opposeEnv: Record + ): 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; + } +} + +export class che_약탈발동 extends BaseWarUnitTrigger { + constructor(unit: WarUnit, raiseType: number) { + super(unit, TriggerPriority.Post + 350, raiseType); + } + + protected actionWar( + self: WarUnit, + oppose: WarUnit, + selfEnv: Record, + _opposeEnv: Record + ): 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('상대를 약탈했다!', LogFormat.PLAIN); + self.getLogger().pushGeneralBattleDetailLog( + `상대에게서 금 ${theftGold.toLocaleString()}, 쌀 ${theftRice.toLocaleString()} 만큼을 약탈했다!`, + LogFormat.PLAIN + ); + oppose.getLogger().pushGeneralActionLog('상대에게 약탈당했다!', LogFormat.PLAIN); + oppose + .getLogger() + .pushGeneralBattleDetailLog( + `상대에게 금 ${theftGold.toLocaleString()}, 쌀 ${theftRice.toLocaleString()} 만큼을 약탈당했다!`, + LogFormat.PLAIN + ); + + this.processConsumableItem(); + return true; + } +} diff --git a/packages/logic/src/war/triggers/che_위압.ts b/packages/logic/src/war/triggers/che_위압.ts new file mode 100644 index 0000000..b385df9 --- /dev/null +++ b/packages/logic/src/war/triggers/che_위압.ts @@ -0,0 +1,59 @@ +import { LogFormat } from '@sammo-ts/logic/logging/types.js'; +import { TriggerPriority } from '@sammo-ts/logic/triggers/core.js'; +import { BaseWarUnitTrigger } from '@sammo-ts/logic/war/triggers.js'; +import type { WarUnit } from '@sammo-ts/logic/war/units.js'; + +type AtmosUnit = WarUnit & { addAtmos: (amount: number) => void }; + +const canAddAtmos = (unit: WarUnit): unit is AtmosUnit => + 'addAtmos' in unit && typeof (unit as { addAtmos?: unknown }).addAtmos === 'function'; + +export class che_위압시도 extends BaseWarUnitTrigger { + constructor(unit: WarUnit) { + super(unit, TriggerPriority.Begin + 100); + } + + protected actionWar( + self: WarUnit, + oppose: WarUnit, + _selfEnv: Record, + _opposeEnv: Record + ): boolean { + if (self.getPhase() !== 0 && oppose.getPhase() !== 0) { + return true; + } + if (self.hasActivatedSkill('위압불가')) { + return true; + } + + self.activateSkill('위압'); + oppose.activateSkill('회피불가', '필살불가', '계략불가'); + return true; + } +} + +export class che_위압발동 extends BaseWarUnitTrigger { + constructor(unit: WarUnit) { + super(unit, TriggerPriority.Post + 700); + } + + protected actionWar( + self: WarUnit, + oppose: WarUnit, + _selfEnv: Record, + _opposeEnv: Record + ): boolean { + if (!self.hasActivatedSkill('위압')) { + return true; + } + + oppose.getLogger().pushGeneralBattleDetailLog('상대에게 위압받았다!', LogFormat.PLAIN); + self.getLogger().pushGeneralBattleDetailLog('상대에게 위압을 줬다!', LogFormat.PLAIN); + oppose.setWarPowerMultiply(0); + if (canAddAtmos(oppose)) { + oppose.addAtmos(-5); + } + + return true; + } +} diff --git a/packages/logic/src/war/triggers/che_의술.ts b/packages/logic/src/war/triggers/che_의술.ts index 8eae52e..2ce6e7a 100644 --- a/packages/logic/src/war/triggers/che_의술.ts +++ b/packages/logic/src/war/triggers/che_의술.ts @@ -5,7 +5,7 @@ import { WarUnitGeneral, type WarUnit } from '@sammo-ts/logic/war/units.js'; import type { WarTriggerModule } from './types.js'; // 의술: 치료 시도 -class AttemptTrigger extends BaseWarUnitTrigger { +export class che_의술시도 extends BaseWarUnitTrigger { constructor(unit: WarUnit) { super(unit, TriggerPriority.Pre + 350); } @@ -35,7 +35,7 @@ class AttemptTrigger extends BaseWarUnitTrigger { } // 의술: 치료 발동 -class ActivateTrigger extends BaseWarUnitTrigger { +export class che_의술발동 extends BaseWarUnitTrigger { constructor(unit: WarUnit) { super(unit, TriggerPriority.Post + 550); } @@ -72,5 +72,5 @@ export const triggerModule: WarTriggerModule = { key: 'che_의술', name: '의술', info: '[전투] 페이즈마다 치료 발동(아군 피해 30% 감소, 부상 회복)', - createTriggerList: (unit) => new WarTriggerCaller(new AttemptTrigger(unit), new ActivateTrigger(unit)), + createTriggerList: (unit) => new WarTriggerCaller(new che_의술시도(unit), new che_의술발동(unit)), }; diff --git a/packages/logic/src/war/triggers/che_저격.ts b/packages/logic/src/war/triggers/che_저격.ts index 701b3f9..5b6be82 100644 --- a/packages/logic/src/war/triggers/che_저격.ts +++ b/packages/logic/src/war/triggers/che_저격.ts @@ -5,7 +5,7 @@ import { WarUnitGeneral, type WarUnit } from '@sammo-ts/logic/war/units.js'; import { clamp } from '@sammo-ts/logic/war/utils.js'; // 저격 시도 트리거: 전투 시작 타이밍에 확률 체크. -export class CheSnipingAttemptTrigger extends BaseWarUnitTrigger { +export class che_저격시도 extends BaseWarUnitTrigger { private readonly ratio: number; private readonly woundMin: number; private readonly woundMax: number; @@ -54,7 +54,7 @@ export class CheSnipingAttemptTrigger extends BaseWarUnitTrigger { } // 저격 발동 트리거: 성공 시 사기 보정과 부상 판정. -export class CheSnipingActivateTrigger extends BaseWarUnitTrigger { +export class che_저격발동 extends BaseWarUnitTrigger { constructor(unit: WarUnit, raiseType: number) { super(unit, TriggerPriority.Post + 100, raiseType); } diff --git a/packages/logic/src/war/triggers/che_저지.ts b/packages/logic/src/war/triggers/che_저지.ts new file mode 100644 index 0000000..b4f108f --- /dev/null +++ b/packages/logic/src/war/triggers/che_저지.ts @@ -0,0 +1,62 @@ +import { LogFormat } from '@sammo-ts/logic/logging/types.js'; +import { TriggerPriority } from '@sammo-ts/logic/triggers/core.js'; +import { BaseWarUnitTrigger } from '../triggers.js'; +import { WarUnitGeneral, type WarUnit } from '../units.js'; + +export class che_저지_시도 extends BaseWarUnitTrigger { + constructor(unit: WarUnit, raiseType: number = 0) { + super(unit, TriggerPriority.Pre, raiseType); + } + protected actionWar(u: WarUnit): boolean { + u.activateSkill('특수', '저지'); + return true; + } +} + +export class che_저지 extends BaseWarUnitTrigger { + constructor(unit: WarUnit, raiseType: number = 0) { + super(unit, TriggerPriority.Post, raiseType); + } + + protected actionWar( + self: WarUnit, + oppose: WarUnit, + selfEnv: Record, + _opposeEnv: Record + ): boolean { + if (!self.hasActivatedSkill('저지')) { + return true; + } + + if (selfEnv['저지발동']) { + return true; + } + selfEnv['저지발동'] = true; + + self.addPhase(-1); + oppose.addPhase(-1); + if (self.getPhase() < self.getMaxPhase()) { + oppose.addBonusPhase(-1); + } + + self.getLogger().pushGeneralBattleDetailLog('상대를 저지했다!', LogFormat.PLAIN); + oppose.getLogger().pushGeneralBattleDetailLog('저지당했다!', LogFormat.PLAIN); + + const calcDamage = oppose.getWarPower() * 0.9; + if (self instanceof WarUnitGeneral) { + self.addDex(oppose.getCrewType(), oppose.getWarPower() * 0.9); + self.addDex(self.getCrewType(), calcDamage); + + self.addLevelExp(calcDamage / 50); + let rice = self.calcRiceConsumption(calcDamage); + rice *= 0.25; + const general = self.getGeneral(); + general.rice = Math.max(0, general.rice - rice); + } + + self.setWarPowerMultiply(0); + oppose.setWarPowerMultiply(0); + + return false; + } +} diff --git a/packages/logic/src/war/triggers/che_진압.ts b/packages/logic/src/war/triggers/che_진압.ts new file mode 100644 index 0000000..dea97da --- /dev/null +++ b/packages/logic/src/war/triggers/che_진압.ts @@ -0,0 +1,13 @@ +import { BaseWarUnitTrigger } from '../triggers.js'; +import type { WarUnit } from '../units.js'; + +export class che_진압 extends BaseWarUnitTrigger { + constructor(unit: WarUnit, raiseType: number = 0) { + super(unit, 0, raiseType); + } + + protected actionWar(self: WarUnit): boolean { + self.activateSkill('반계불가', '격노불가'); + return true; + } +} diff --git a/packages/logic/src/war/triggers/che_퇴각부상무효.ts b/packages/logic/src/war/triggers/che_퇴각부상무효.ts index 2d22417..599366c 100644 --- a/packages/logic/src/war/triggers/che_퇴각부상무효.ts +++ b/packages/logic/src/war/triggers/che_퇴각부상무효.ts @@ -3,7 +3,7 @@ import { BaseWarUnitTrigger } from '@sammo-ts/logic/war/triggers.js'; import { WarUnitGeneral, type WarUnit } from '@sammo-ts/logic/war/units.js'; // 전투 종료 부상을 무효화하는 상태를 부여한다. -export class CheRetreatNoWoundTrigger extends BaseWarUnitTrigger { +export class che_퇴각부상무효 extends BaseWarUnitTrigger { constructor(unit: WarUnit) { super(unit, TriggerPriority.Begin + 300); } diff --git a/packages/logic/src/war/triggers/che_필살.ts b/packages/logic/src/war/triggers/che_필살.ts index bd14386..e6673f3 100644 --- a/packages/logic/src/war/triggers/che_필살.ts +++ b/packages/logic/src/war/triggers/che_필살.ts @@ -5,7 +5,7 @@ import { WarUnitGeneral, type WarUnit } from '@sammo-ts/logic/war/units.js'; import type { WarTriggerModule } from './types.js'; // 기본 필살: 시도 단계 -class AttemptTrigger extends BaseWarUnitTrigger { +export class che_필살시도 extends BaseWarUnitTrigger { constructor(unit: WarUnit) { super(unit, TriggerPriority.Pre + 120); } @@ -34,7 +34,7 @@ class AttemptTrigger extends BaseWarUnitTrigger { } // 기본 필살: 발동 단계 -class ActivateTrigger extends BaseWarUnitTrigger { +export class che_필살발동 extends BaseWarUnitTrigger { constructor(unit: WarUnit) { super(unit, TriggerPriority.Post + 400); } @@ -61,9 +61,29 @@ class ActivateTrigger extends BaseWarUnitTrigger { } } +export class che_필살강화_회피불가 extends BaseWarUnitTrigger { + constructor(unit: WarUnit) { + super(unit, TriggerPriority.Pre + 150); + } + + protected actionWar( + self: WarUnit, + oppose: WarUnit, + _selfEnv: Record, + _opposeEnv: Record + ): boolean { + if (!self.hasActivatedSkill('필살')) { + return true; + } + + oppose.activateSkill('회피불가'); + return true; + } +} + export const triggerModule: WarTriggerModule = { key: 'che_필살', name: '필살', info: '[전투] 페이즈마다 확률로 필살 발동', - createTriggerList: (unit) => new WarTriggerCaller(new AttemptTrigger(unit), new ActivateTrigger(unit)), + createTriggerList: (unit) => new WarTriggerCaller(new che_필살시도(unit), new che_필살발동(unit)), }; diff --git a/packages/logic/src/war/triggers/che_훈련.ts b/packages/logic/src/war/triggers/che_훈련.ts new file mode 100644 index 0000000..40f2382 --- /dev/null +++ b/packages/logic/src/war/triggers/che_훈련.ts @@ -0,0 +1,17 @@ +import { BaseWarUnitTrigger } from '../triggers.js'; +import type { WarUnit } from '../units.js'; + +export class che_훈련 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.addTrain(this.amount); + this.processConsumableItem(); + return true; + } +}