WarUnitTrigger 부분 재정리

This commit is contained in:
2026-01-07 17:44:49 +00:00
parent 38a8d33242
commit b6e1c18203
36 changed files with 563 additions and 692 deletions
@@ -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<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: '구정신단경',
@@ -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)
);
},
};
@@ -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));
},
};
@@ -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));
},
};
@@ -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)
);
},
};
@@ -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)
);
},
};
@@ -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<ItemModule['onCalcStat']>,
getBattlePhaseTriggerList: (context) => {
if (!context.unit) return null;
return new WarTriggerCaller(new CheAmuletTrigger(context.unit));
return new WarTriggerCaller(new che_부적(context.unit));
},
};
+2 -17
View File
@@ -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)
);
},
};
+3 -100
View File
@@ -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<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: '옥벽',
@@ -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)
);
},
};
@@ -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)
);
},
};
@@ -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)
);
},
};
@@ -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)
);
},
};
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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('상대를 <C>저지</>했다!', LogFormat.PLAIN);
oppose.getLogger().pushGeneralBattleDetailLog('<R>저지</>당했다!', 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)
);
},
};
@@ -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));
},
};
+2 -17
View File
@@ -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)
);
},
};