slave-princess-charlotte/data/Script/item/item-base.js
2025-10-12 13:17:46 -05:00

853 lines
23 KiB
JavaScript

var ItemPackageControl = {
getItemSelectionObject: function(item) {
var obj;
var type = item.getItemType();
var arr = [
null, RecoveryItemSelection, EntireRecoveryItemSelection, DamageItemSelection, DopingItemSelection,
ClassChangeItemSelection, SkillChangeItemSelection, KeyItemSelection, QuickItemSelection,
TeleportationItemSelection, RescueItemSelection, ResurrectionItemSelection, DurabilityChangeItemSelection,
StealItemSelection, StateItemSelection, StateRecoveryItemSelection, SwitchItemSelection,
FusionItemSelection, MetamorphozeItemSelection
];
if (type === ItemType.CUSTOM) {
obj = this.getCustomItemSelectionObject(item, item.getCustomKeyword());
}
else if (type === ItemType.UNUSABLE) {
return null;
}
else {
obj = arr[type];
}
return createObject(obj);
},
getItemUseParent: function(item) {
var obj, parent;
var type = item.getItemType();
var arr = [
null, RecoveryItemUse, EntireRecoveryItemUse, DamageItemUse, DopingItemUse,
ClassChangeItemUse, SkillChangeItemUse, KeyItemUse, QuickItemUse,
TeleportationItemUse, RescueItemUse, ResurrectionItemUse, DurabilityChangeItemUse,
StealItemUse, StateItemUse, StateRecoveryItemUse, SwitchItemUse,
FusionItemUse, MetamorphozeItemUse
];
if (type === ItemType.CUSTOM) {
obj = this.getCustomItemUseObject(item, item.getCustomKeyword());
}
else if (type === ItemType.UNUSABLE) {
return null;
}
else {
obj = arr[type];
}
// getItemSelectionObjectやgetItemInfoObjectと異なり、
// RecoveryItemUseなどを返すのではなく、
// そうしたオブジェクトを包括するオブジェクトを返す。
parent = createObject(ItemUseParent);
parent._itemUseObject = createObject(obj);
return parent;
},
getItemInfoObject: function(item) {
var obj;
var type = item.getItemType();
var arr = [
UnusableItemInfo, RecoveryItemInfo, EntireRecoveryItemInfo, DamageItemInfo, DopingItemInfo,
ClassChangeItemInfo, SkillChangeItemInfo, KeyItemInfo, QuickItemInfo,
TeleportationItemInfo, RescueItemInfo, ResurrectionItemInfo, DurabilityItemInfo,
StealItemInfo, StateItemInfo, StateRecoveryItemInfo, SwitchItemInfo,
FusionItemInfo, MetamorphozeItemInfo
];
if (type === ItemType.CUSTOM) {
obj = this.getCustomItemInfoObject(item, item.getCustomKeyword());
}
else {
obj = arr[type];
}
return createObject(obj);
},
getItemAvailabilityObject: function(item) {
var obj;
var type = item.getItemType();
var arr = [
UnusableItemAvailability, RecoveryItemAvailability, EntireRecoveryItemAvailability, DamageItemAvailability, DopingItemAvailability,
ClassChangeItemAvailability, SkillChangeItemAvailability, KeyItemAvailability, QuickItemAvailability,
TeleportationItemAvailability, RescueItemAvailability, ResurrectionItemAvailability, DurabilityChangeItemAvailability,
StealItemAvailability, StateItemAvailability, StateRecoveryItemAvailability, SwitchItemAvailability,
FusionItemAvailability, MetamorphozeItemAvailability
];
if (type === ItemType.CUSTOM) {
obj = this.getCustomItemAvailabilityObject(item, item.getCustomKeyword());
}
else {
obj = arr[type];
}
return createObject(obj);
},
getItemAIObject: function(item) {
var obj;
var type = item.getItemType();
var arr = [
UnusableItemAI, RecoveryItemAI, EntireRecoveryItemAI, DamageItemAI, DopingItemAI,
ClassChangeItemAI, SkillChangeItemAI, KeyItemAI, QuickItemAI,
TeleportationItemAI, RescueItemAI, ResurrectionItemAI, DurabilityChangeItemAI,
StealItemAI, StateItemAI, StateRecoveryItemAI, SwitchItemAI,
FusionItemAI, MetamorphozeItemAI
];
if (type === ItemType.CUSTOM) {
obj = this.getCustomItemAIObject(item, item.getCustomKeyword());
}
else {
obj = arr[type];
}
return createObject(obj);
},
getCustomItemSelectionObject: function(item, keyword) {
return null;
},
getCustomItemUseObject: function(item, keyword) {
return null;
},
getCustomItemInfoObject: function(item, keyword) {
return null;
},
getCustomItemAvailabilityObject: function(item, keyword) {
return null;
},
getCustomItemAIObject: function(item, keyword) {
return null;
}
};
var BaseItemSelection = defineObject(BaseObject,
{
_unit: null,
_item: null,
_targetUnit: null,
_targetPos: null,
_targetClass: null,
_targetItem: null,
_targetMetamorphoze: null,
_isSelection: false,
_posSelector: null,
enterItemSelectionCycle: function(unit, item) {
this._unit = unit;
this._item = item;
this._targetUnit = this._unit;
this._targetPos = createPos(this._unit.getMapX(), this._unit.getMapY());
this._targetClass = null;
this._targetItem = null;
this._isSelection = false;
this._posSelector = createObject(PosSelector);
return this.setInitialSelection();
},
moveItemSelectionCycle: function() {
var targetUnit;
var result = this._posSelector.movePosSelector();
if (result === PosSelectorResult.SELECT) {
if (this.isPosSelectable()) {
targetUnit = this._posSelector.getSelectorTarget(false);
if (targetUnit !== null) {
this._targetUnit = targetUnit;
}
this._isSelection = true;
this._posSelector.endPosSelector();
return MoveResult.END;
}
}
else if (result === PosSelectorResult.CANCEL) {
this._isSelection = false;
this._posSelector.endPosSelector();
return MoveResult.END;
}
return MoveResult.CONTINUE;
},
drawItemSelectionCycle: function() {
this._posSelector.drawPosSelector();
},
setUnitSelection: function() {
var filter = this.getUnitFilter();
var indexArray = IndexArray.createIndexArray(this._unit.getMapX(), this._unit.getMapY(), this._item);
indexArray = this._getUnitOnlyIndexArray(this._unit, indexArray);
this._posSelector.setUnitOnly(this._unit, this._item, indexArray, PosMenuType.Item, filter);
this.setFirstPos();
},
// アイテムを特定の位置に対して使用する場合に呼ばれる
setPosSelection: function() {
var indexArray = IndexArray.createIndexArray(this._unit.getMapX(), this._unit.getMapY(), this._item);
this._posSelector.setPosOnly(this._unit, this._item, indexArray, PosMenuType.Item);
this.setFirstPos();
},
setFirstPos: function() {
this._posSelector.setFirstPos();
},
isPosSelectable: function() {
return this._posSelector.getSelectorTarget(true) !== null;
},
getUnitFilter: function() {
return FilterControl.getBestFilter(this._unit.getUnitType(), this._item.getFilterFlag());
},
setInitialSelection: function() {
var rangeType = this._item.getRangeType();
if (rangeType === SelectionRangeType.SELFONLY) {
this._isSelection = true;
return EnterResult.NOTENTER;
}
else {
// 既定では、アイテムはユニットに対して使用できる
this.setUnitSelection();
}
return EnterResult.OK;
},
isSelection: function() {
return this._isSelection;
},
getResultItemTargetInfo: function() {
var itemTargetInfo = StructureBuilder.buildItemTargetInfo();
// unitとitemは、呼び出し側が設定する
itemTargetInfo.targetUnit = this._targetUnit;
itemTargetInfo.targetPos = this._targetPos;
itemTargetInfo.targetClass = this._targetClass;
itemTargetInfo.targetItem = this._targetItem;
itemTargetInfo.targetMetamorphoze = this._targetMetamorphoze;
return itemTargetInfo;
},
_getUnitOnlyIndexArray: function(unit, indexArray) {
var i, index, x, y;
var indexArrayNew = [];
var count = indexArray.length;
var obj = ItemPackageControl.getItemAvailabilityObject(this._item);
if (obj === null) {
return indexArrayNew;
}
for (i = 0; i < count; i++) {
index = indexArray[i];
x = CurrentMap.getX(index);
y = CurrentMap.getY(index);
if (obj.isPosEnabled(unit, this._item, x, y)) {
indexArrayNew.push(index);
}
}
return indexArrayNew;
}
}
);
var BaseItemUse = defineObject(BaseObject,
{
enterMainUseCycle: function(itemUseParent) {
return EnterResult.NOTENTER;
},
moveMainUseCycle: function() {
return MoveResult.END;
},
drawMainUseCycle: function() {
},
mainAction: function() {
},
// enterMainUseCycleより前に呼ばれる
getItemAnimePos: function(itemUseParent, animeData) {
return null;
},
getUnitBasePos: function(itemUseParent, animeData) {
var x, y, size, pos;
var targetUnit = itemUseParent.getItemTargetInfo().targetUnit;
if (Miscellaneous.isPrepareScene()) {
size = Miscellaneous.getFirstKeySpriteSize(animeData, 0);
x = LayoutControl.getCenterX(-1, size.width);
y = LayoutControl.getCenterY(-1, size.height);
pos = createPos(x, y);
}
else {
x = LayoutControl.getPixelX(targetUnit.getMapX());
y = LayoutControl.getPixelY(targetUnit.getMapY());
pos = LayoutControl.getMapAnimationPos(x, y, animeData);
}
return pos;
}
}
);
// ItemUseParentが使用される前に、
// BaseItemSelectionが使用されているとは限らない点に注意。
// イベントコマンドの「アイテムの使用」や、敵がアイテムを使用する場合は、
// 選択モードを介さずにBaseItemUseが使用される。
var ItemUseParent = defineObject(BaseObject,
{
_itemUseObject: null,
_itemTargetInfo: null,
_isItemDecrementDisabled: false,
_isItemSkipMode: false,
_straightFlow: null,
enterUseCycle: function(itemTargetInfo) {
this._prepareMemberData(itemTargetInfo);
return this._completeMemberData(itemTargetInfo);
},
moveUseCycle: function() {
if (InputControl.isStartAction()) {
this.setItemSkipMode(true);
}
if (this._straightFlow.moveStraightFlow() !== MoveResult.CONTINUE) {
if (this._itemTargetInfo.isPlayerSideCall) {
// 自軍側でのアイテムや杖を通じたコマンド経由において、
// ここで無条件にスキップを無効にすることで後続操作(攻撃など)にまでスキップが影響しないようにする。
this.setItemSkipMode(false);
}
this.decreaseItem();
return MoveResult.END;
}
return MoveResult.CONTINUE;
},
drawUseCycle: function() {
this._straightFlow.drawStraightFlow();
},
disableItemDecrement: function() {
this._isItemDecrementDisabled = true;
},
isItemSkipMode: function() {
return CurrentMap.isCompleteSkipMode();
},
setItemSkipMode: function(isSkipMode) {
CurrentMap.setTurnSkipMode(isSkipMode);
},
decreaseItem: function() {
if (!this._isItemDecrementDisabled) {
// アイテムの耐久を減らす
ItemControl.decreaseItem(this._itemTargetInfo.unit, this._itemTargetInfo.item);
}
},
getItemUseObject: function() {
return this._itemUseObject;
},
getItemTargetInfo: function() {
return this._itemTargetInfo;
},
_prepareMemberData: function(itemTargetInfo) {
this._itemTargetInfo = itemTargetInfo;
this._isItemDecrementDisabled = false;
this._isItemSkipMode = false;
this._straightFlow = createObject(StraightFlow);
},
_completeMemberData: function(itemTargetInfo) {
var result;
this._straightFlow.setStraightFlowData(this);
this._pushFlowEntries(this._straightFlow);
result = this._straightFlow.enterStraightFlow();
if (result === EnterResult.NOTENTER) {
this.decreaseItem();
}
return result;
},
_pushFlowEntries: function(straightFlow) {
straightFlow.pushFlowEntry(ItemTitleFlowEntry);
straightFlow.pushFlowEntry(ItemStartScrollFlowEntry);
straightFlow.pushFlowEntry(ItemMainFlowEntry);
straightFlow.pushFlowEntry(ItemExpFlowEntry);
}
}
);
var ItemTitleFlowEntry = defineObject(BaseFlowEntry,
{
_itemUseParent: null,
_counter: null,
enterFlowEntry: function(itemUseParent) {
this._prepareMemberData(itemUseParent);
return this._completeMemberData(itemUseParent);
},
moveFlowEntry: function() {
if (this._itemUseParent.isItemSkipMode()) {
return MoveResult.END;
}
if (this._counter.moveCycleCounter() !== MoveResult.CONTINUE) {
return MoveResult.END;
}
return MoveResult.CONTINUE;
},
drawFlowEntry: function() {
var x, y;
var itemTargetInfo = this._itemUseParent.getItemTargetInfo();
var textui = root.queryTextUI('itemuse_title');
var color = textui.getColor();
var font = textui.getFont();
var pic = textui.getUIImage();
var text = itemTargetInfo.item.getName();
var width = (TitleRenderer.getTitlePartsCount(text, font) + 2) * TitleRenderer.getTitlePartsWidth();
x = LayoutControl.getUnitCenterX(itemTargetInfo.unit, width, 0);
y = LayoutControl.getUnitBaseY(itemTargetInfo.unit, TitleRenderer.getTitlePartsHeight()) - 20;
TextRenderer.drawTitleText(x, y, text, color, font, TextFormat.CENTER, pic);
},
_prepareMemberData: function(itemUseParent) {
this._itemUseParent = itemUseParent;
this._counter = createObject(CycleCounter);
},
_completeMemberData: function(itemUseParent) {
if (Miscellaneous.isPrepareScene()) {
return EnterResult.NOTENTER;
}
if (this._itemUseParent.isItemSkipMode()) {
return EnterResult.NOTENTER;
}
this._counter.setCounterInfo(36);
this._playItemUseSound();
return EnterResult.OK;
},
_playItemUseSound: function() {
MediaControl.soundDirect('itemuse');
}
}
);
// 敵がアイテムを使用した場合に、対象に向かってスクロールする。
// 見出しの後に表示するために、AutoActionCursorに含めていない。
var ItemStartScrollFlowEntry = defineObject(BaseFlowEntry,
{
_itemUseParent: null,
_mapLineScroll: null,
enterFlowEntry: function(itemUseParent) {
this._prepareMemberData(itemUseParent);
return this._completeMemberData(itemUseParent);
},
moveFlowEntry: function() {
return this._mapLineScroll.moveLineScroll();
},
drawFlowEntry: function() {
},
_prepareMemberData: function(itemUseParent) {
this._itemUseParent = itemUseParent;
this._mapLineScroll = createObject(MapLineScroll);
},
_completeMemberData: function(itemUseParent) {
var x, y;
var itemTargetInfo = itemUseParent.getItemTargetInfo();
var unit = itemTargetInfo.unit;
if (itemUseParent.isItemSkipMode()) {
return EnterResult.NOTENTER;
}
if (itemTargetInfo.targetUnit !== null) {
x = itemTargetInfo.targetUnit.getMapX();
y = itemTargetInfo.targetUnit.getMapY();
}
else if (itemTargetInfo.targetPos !== null) {
x = itemTargetInfo.targetPos.x;
y = itemTargetInfo.targetPos.y;
}
else {
return EnterResult.NOTENTER;
}
if (unit.getUnitType() === UnitType.PLAYER || MapView.isVisible(x, y)) {
return EnterResult.NOTENTER;
}
this._mapLineScroll.startLineScroll(x, y);
return EnterResult.OK;
}
}
);
var ItemMainMode = {
ANIME: 0,
USE: 1
};
// そのアイテム特有の処理を行う。
// たとえば、HP回復アイテムならば回復処理を行う。
var ItemMainFlowEntry = defineObject(BaseFlowEntry,
{
_itemUseParent: null,
_dynamicAnime: null,
enterFlowEntry: function(itemUseParent) {
this._prepareMemberData(itemUseParent);
return this._completeMemberData(itemUseParent);
},
moveFlowEntry: function() {
var result = MoveResult.CONTINUE;
var mode = this.getCycleMode();
if (mode === ItemMainMode.ANIME) {
result = this._moveAnime();
}
else if (mode === ItemMainMode.USE) {
result = this._moveUse();
}
return result;
},
drawFlowEntry: function() {
var mode = this.getCycleMode();
if (mode === ItemMainMode.ANIME) {
this._drawAnime();
}
else if (mode === ItemMainMode.USE) {
this._drawUse();
}
},
_prepareMemberData: function(itemUseParent) {
this._itemUseParent = itemUseParent;
this._dynamicAnime = createObject(DynamicAnime);
},
_completeMemberData: function(itemUseParent) {
var animeData = itemUseParent.getItemTargetInfo().item.getItemAnime();
var pos = itemUseParent.getItemUseObject().getItemAnimePos(itemUseParent, animeData);
if (pos === null || itemUseParent.isItemSkipMode()) {
return this._changeMainUse() ? EnterResult.OK : EnterResult.NOTENTER;
}
if (animeData !== null) {
this._dynamicAnime.startDynamicAnime(animeData, pos.x, pos.y);
this.changeCycleMode(ItemMainMode.ANIME);
return EnterResult.OK;
}
return this._changeMainUse();
},
_moveAnime: function() {
var result = this._dynamicAnime.moveDynamicAnime();
if (result !== MoveResult.CONTINUE) {
if (this._changeMainUse()) {
result = MoveResult.CONTINUE;
}
}
return result;
},
_moveUse: function() {
return this._itemUseParent.getItemUseObject().moveMainUseCycle();
},
_drawAnime: function() {
this._dynamicAnime.drawDynamicAnime();
},
_drawUse: function() {
this._itemUseParent.getItemUseObject().drawMainUseCycle();
},
_changeMainUse: function() {
var result = this._itemUseParent.getItemUseObject().enterMainUseCycle(this._itemUseParent, this._itemUseParent.isItemSkipMode()) === EnterResult.OK;
if (result) {
this.changeCycleMode(ItemMainMode.USE);
}
return result;
}
}
);
// アイテムに設定されている経験値を取得する
var ItemExpFlowEntry = defineObject(BaseFlowEntry,
{
_itemUseParent: null,
_dynamicEvent: null,
enterFlowEntry: function(itemUseParent) {
this._prepareMemberData(itemUseParent);
return this._completeMemberData(itemUseParent);
},
moveFlowEntry: function() {
return this._dynamicEvent.moveDynamicEvent();
},
drawFlowEntry: function() {
},
_prepareMemberData: function(itemUseParent) {
this._itemUseParent = itemUseParent;
this._dynamicEvent = createObject(DynamicEvent);
},
_completeMemberData: function(itemUseParent) {
var generator;
var exp = this._getItemExperience(itemUseParent);
var itemTargetInfo = itemUseParent.getItemTargetInfo();
var unit = itemTargetInfo.unit;
var type = unit.getUnitType();
if (exp === 0 || type !== UnitType.PLAYER) {
return EnterResult.NOTENTER;
}
generator = this._dynamicEvent.acquireEventGenerator();
generator.experiencePlus(unit, exp, itemUseParent.isItemSkipMode());
return this._dynamicEvent.executeDynamicEvent();
},
_getItemExperience: function(itemUseParent) {
var itemTargetInfo = itemUseParent.getItemTargetInfo();
var unit = itemTargetInfo.unit;
var exp = itemTargetInfo.item.getExp();
return ExperienceCalculator.getBestExperience(unit, exp);
}
}
);
// メニューなどで表示されるアイテム情報を描画する
var BaseItemInfo = defineObject(BaseObject,
{
_item: null,
setInfoItem: function(item) {
this._item = item;
},
moveItemInfoCycle: function() {
return MoveResult.CONTINUE;
},
drawItemInfoCycle: function(x, y) {
},
drawRange: function(x, y, rangeValue, rangeType) {
var textui = this.getWindowTextUI();
var color = textui.getColor();
var font = textui.getFont();
ItemInfoRenderer.drawKeyword(x, y, root.queryCommand('range_capacity'));
x += ItemInfoRenderer.getSpaceX();
if (rangeType === SelectionRangeType.SELFONLY) {
TextRenderer.drawKeywordText(x, y, StringTable.Range_Self, -1, color, font);
}
else if (rangeType === SelectionRangeType.MULTI) {
NumberRenderer.drawRightNumber(x, y, rangeValue);
}
else if (rangeType === SelectionRangeType.ALL) {
TextRenderer.drawKeywordText(x, y, StringTable.Range_All, -1, color, font);
}
},
getInfoPartsCount: function() {
return 0;
},
getItemTypeName: function(name) {
var text;
if (this._item.isWand()) {
text = StringTable.ItemWord_SuffixWand;
}
else {
text = StringTable.ItemWord_SuffixItem;
}
return name + text;
},
getWindowTextUI: function() {
return ItemInfoRenderer.getTextUI();
}
}
);
// ItemControl.isItemUsableは、ユニットがそのアイテムをそもそも使用可能であるかを調べる。
// BaseItemAvailabilityは、ユニットがそのアイテムを現在使用可能であるかを調べる。
// たとえば、対象が範囲内に入っているかどうかなどを考慮する。
// BaseItemAvailabilityは自軍がアイテムを使用する場合に参照され、
// 敵軍がアイテムを使用する場合はAI処理も統合されているBaseItemAIが参照される。
var BaseItemAvailability = defineObject(BaseObject,
{
isItemAvailableCondition: function(unit, item) {
var rangeType = item.getRangeType();
if (rangeType === SelectionRangeType.SELFONLY) {
return this._checkSelfOnly(unit, item);
}
else if (rangeType === SelectionRangeType.MULTI) {
return this._checkMulti(unit, item);
}
else if (rangeType === SelectionRangeType.ALL) {
return this._checkAll(unit, item);
}
return false;
},
isPosEnabled: function(unit, item, x, y) {
var targetUnit;
targetUnit = PosChecker.getUnitFromPos(x, y);
if (targetUnit !== null && targetUnit !== unit) {
if (FilterControl.isBestUnitTypeAllowed(unit.getUnitType(), targetUnit.getUnitType(), item.getFilterFlag())) {
return this._isCondition(unit, targetUnit, item) && this.isItemAllowed(unit, targetUnit, item);
}
}
return false;
},
isItemAllowed: function(unit, targetUnit, item) {
return true;
},
_checkSelfOnly: function(unit, item) {
return this._isCondition(unit, unit, item) && this.isItemAllowed(unit, unit, item);
},
_checkMulti: function(unit, item) {
var i, index, x, y;
var indexArray = IndexArray.createIndexArray(unit.getMapX(), unit.getMapY(), item);
var count = indexArray.length;
for (i = 0; i < count; i++) {
index = indexArray[i];
x = CurrentMap.getX(index);
y = CurrentMap.getY(index);
if (this.isPosEnabled(unit, item, x, y)) {
return true;
}
}
return false;
},
_checkAll: function(unit, item) {
var i, j, count, list, targetUnit;
var filter = FilterControl.getBestFilter(unit.getUnitType(), item.getFilterFlag());
var listArray = FilterControl.getListArray(filter);
var listCount = listArray.length;
for (i = 0; i < listCount; i++) {
list = listArray[i];
count = list.getCount();
for (j = 0; j < count; j++) {
targetUnit = list.getData(j);
if (unit !== targetUnit && this._isCondition(unit, targetUnit, item) && this.isItemAllowed(unit, targetUnit, item)) {
return true;
}
}
}
return false;
},
_isCondition: function(unit, targetUnit, item) {
return item.getTargetAggregation().isCondition(targetUnit);
}
}
);
var BaseItemAI = defineObject(BaseObject,
{
getItemScore: function(unit, combination) {
return AIValue.MIN_SCORE;
},
getUnitFilter: function(unit, item) {
return FilterControl.getBestFilter(unit.getUnitType(), item.getFilterFlag());
},
getActionTargetType: function(unit, item) {
if (!item.isWeapon() && item.getRangeType() === SelectionRangeType.SELFONLY) {
return ActionTargetType.SINGLE;
}
return ActionTargetType.UNIT;
}
}
);