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)
);
},
};
@@ -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<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(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<string, unknown>,
_opposeEnv: Record<string, unknown>
): boolean {
if (!self.hasActivatedSkill('격노')) {
return true;
}
const targetAct = oppose.hasActivatedSkill('필살') ? '필살 공격' : '회피 시도';
const is진노 = self.hasActivatedSkill('진노');
const reaction = is진노 ? '진노' : '격노';
self.getLogger().pushGeneralBattleDetailLog(`상대의 ${targetAct}에 <C>${reaction}</>했다!</>`, LogFormat.PLAIN);
oppose
.getLogger()
.pushGeneralBattleDetailLog(`${targetAct}에 상대가 <R>${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(
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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(
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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(
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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<string, unknown>,
opposeEnv: Record<string, unknown>
): 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(
`<C>반계</>로 상대의 <D>${opposeMagic}</>을 되돌렸다!`,
LogFormat.PLAIN
);
oppose.getLogger().pushGeneralBattleDetailLog(`<D>${opposeMagic}</>을 <R>역으로</> 당했다!`, 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(
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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<string, unknown>,
_opposeEnv: Record<string, unknown>
): boolean {
if (!self.hasActivatedSkill('위압')) {
return true;
}
oppose.getLogger().pushGeneralBattleDetailLog('상대에게 <R>위압</>받았다!', LogFormat.PLAIN);
self.getLogger().pushGeneralBattleDetailLog('상대에게 <C>위압</>을 줬다!', 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(
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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('상대를 <C>저격</>했다!', LogFormat.PLAIN);
self.getLogger().pushGeneralBattleDetailLog('상대를 <C>저격</>했다!', LogFormat.PLAIN);
oppose.getLogger().pushGeneralActionLog('상대에게 <R>저격</>당했다!', LogFormat.PLAIN);
oppose.getLogger().pushGeneralBattleDetailLog('상대에게 <R>저격</>당했다!', LogFormat.PLAIN);
} else {
self.getLogger().pushGeneralActionLog('성벽 수비대장을 <C>저격</>했다!', LogFormat.PLAIN);
self.getLogger().pushGeneralBattleDetailLog('성벽 수비대장을 <C>저격</>했다!', 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,
};
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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(
@@ -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<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(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<string, unknown>,
_opposeEnv: Record<string, unknown>
): boolean {
if (!self.hasActivatedSkill('격노')) {
return true;
}
const targetAct = oppose.hasActivatedSkill('필살') ? '필살 공격' : '회피 시도';
const is진노 = self.hasActivatedSkill('진노');
const reaction = is진노 ? '진노' : '격노';
self.getLogger().pushGeneralBattleDetailLog(`상대의 ${targetAct}에 <C>${reaction}</>했다!</>`, LogFormat.PLAIN);
oppose
.getLogger()
.pushGeneralBattleDetailLog(`${targetAct}에 상대가 <R>${reaction}</>했다!</>`, LogFormat.PLAIN);
if (is진노) {
self.addBonusPhase(1);
}
self.multiplyWarPowerMultiply(self.criticalDamage());
return true;
}
}
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): boolean {
self.activateSkill('부상무효');
return true;
}
}
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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;
}
}
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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<string, unknown>,
opposeEnv: Record<string, unknown>
): 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(
`<C>반계</>로 상대의 <D>${opposeMagic}</>을 되돌렸다!`,
LogFormat.PLAIN
);
oppose.getLogger().pushGeneralBattleDetailLog(`<D>${opposeMagic}</>을 <R>역으로</> 당했다!`, LogFormat.PLAIN);
self.multiplyWarPowerMultiply(damage);
return true;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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<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;
}
}
export class che_약탈발동 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;
}
}
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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<string, unknown>,
_opposeEnv: Record<string, unknown>
): boolean {
if (!self.hasActivatedSkill('위압')) {
return true;
}
oppose.getLogger().pushGeneralBattleDetailLog('상대에게 <R>위압</>받았다!', LogFormat.PLAIN);
self.getLogger().pushGeneralBattleDetailLog('상대에게 <C>위압</>을 줬다!', LogFormat.PLAIN);
oppose.setWarPowerMultiply(0);
if (canAddAtmos(oppose)) {
oppose.addAtmos(-5);
}
return true;
}
}
@@ -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)),
};
@@ -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);
}
@@ -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<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;
}
}
@@ -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;
}
}
@@ -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);
}
+23 -3
View File
@@ -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<string, unknown>,
_opposeEnv: Record<string, unknown>
): 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)),
};
@@ -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;
}
}