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

780 lines
19 KiB
JavaScript

var ItemControl = {
decreaseItem: function(unit, item) {
this.decreaseLimit(unit, item);
if (this.isItemBroken(item)) {
this.lostItem(unit, item);
}
},
decreaseLimit: function(unit, item) {
var limit;
// 耐久が0のアイテムは減らない
if (item.getLimitMax() === 0) {
return;
}
if (item.isWeapon()) {
// 武器が破損している場合は減らない
if (item.getLimit() === WeaponLimitValue.BROKEN) {
return;
}
}
limit = item.getLimit() - 1;
item.setLimit(limit);
},
lostItem: function(unit, item) {
var weaponType = item.getWeaponType();
if (weaponType.getBreakedWeapon() !== null) {
// 「破損時の武器」が設定されている場合は、破損状態を示す値を設定する
item.setLimit(WeaponLimitValue.BROKEN);
return;
}
if (unit === null) {
StockItemControl.cutStockItem(StockItemControl.getIndexFromItem(item));
}
else {
this.deleteItem(unit, item);
}
},
deleteItem: function(unit, item) {
var i;
var count = UnitItemControl.getPossessionItemCount(unit);
for (i = 0; i < count; i++) {
if (UnitItemControl.getItem(unit, i) === item) {
// unitのアイテム欄から外す
UnitItemControl.cutItem(unit, i);
return true;
}
}
return false;
},
deleteTrophy: function(unit, item) {
var i, trophy;
var list = unit.getDropTrophyList();
var count = list.getCount();
for (i = 0; i < count; i++) {
trophy = list.getData(i);
if (ItemControl.compareItem(trophy.getItem(), item)) {
// itemと同じidのアイテムがドロップトロフィーに含まれるため削除
root.getCurrentSession().getTrophyEditor().deleteTrophy(list, trophy);
return true;
}
}
return false;
},
isItemBroken: function(item) {
// 耐久が無限でないアイテムの耐久が0であるか調べる
return item.getLimitMax() !== 0 && item.getLimit() === 0;
},
// 後のバージョンで削除
isWeaponBroken: function(weapon) {
return this.isItemBroken(weapon);
},
// 後のバージョンで削除
isWeaponLimitless: function(unit, weapon) {
return false;
},
isWeaponTypeAllowed: function(refList, weapon) {
var i;
var count = refList.getTypeCount();
for (i = 0; i < count; i++) {
if (weapon.isWeaponTypeMatched(refList.getTypeData(i))) {
break;
}
}
if (i === count) {
return false;
}
return true;
},
getEquippedWeapon: function(unit) {
var i, item, count;
if (unit === null) {
return null;
}
count = UnitItemControl.getPossessionItemCount(unit);
// 装備している武器とは、アイテム欄の中で先頭の武器
for (i = 0; i < count; i++) {
item = UnitItemControl.getItem(unit, i);
if (item !== null && this.isWeaponAvailable(unit, item)) {
return item;
}
}
return null;
},
setEquippedWeapon: function(unit, targetItem) {
var i, item;
var count = UnitItemControl.getPossessionItemCount(unit);
var fastIndex = -1, targetIndex = -1;
// unitがtargetItemの武器を装備する。
// targetItemはアイテム欄の先頭に配置される。
for (i = 0; i < count; i++) {
item = UnitItemControl.getItem(unit, i);
if (item !== null && fastIndex === -1) {
// アイテム欄の中で先頭のアイテムのインデックスを保存
fastIndex = i;
}
if (item === targetItem) {
// 装備するアイテムのインデックスを保存
targetIndex = i;
}
}
if (fastIndex === -1 || targetIndex === -1) {
return;
}
// 交換先が一致する場合は交換しない
if (fastIndex === targetIndex) {
return;
}
// アイテムを入れ替える
item = UnitItemControl.getItem(unit, fastIndex);
UnitItemControl.setItem(unit, fastIndex, targetItem);
UnitItemControl.setItem(unit, targetIndex, item);
this.updatePossessionItem(unit);
},
// このメソッドは、アイテム欄に変化が生じた場合に呼ばれる。
// たとえば、アイテム装備、増加、交換、ストック交換、武器耐久ゼロなど。
updatePossessionItem: function(unit) {
var scene = root.getCurrentScene();
// シーンがFREEでもEVENTでもない場合は、常にHPは最大HPと一致する。
// この処理を忘れた場合は、アイテム交換やアイテム増減でHPが変化する。
if (scene !== SceneType.FREE && scene !== SceneType.EVENT) {
unit.setHp(ParamBonus.getMhp(unit));
}
// HPは最大HPを超えてはならない
if (unit.getHp() > ParamBonus.getMhp(unit)) {
unit.setHp(ParamBonus.getMhp(unit));
}
else if (unit.getHp() < 1) {
unit.setHp(1);
}
},
// unitがitemを装備できるか調べる。
// unitがitemを装備しているか調べるのではない。
isWeaponAvailable: function(unit, item) {
if (item === null) {
return false;
}
// itemが武器でない場合は装備できない
if (!item.isWeapon()) {
return false;
}
// 「熟練度」を調べる
if (!this._isWeaponLevel(unit, item)) {
return false;
}
// 「戦士系」などが一致するか調べる
if (!this._compareTemplateAndCategory(unit, item)) {
return false;
}
// クラスの「装備可能武器」のリストに入っているか調べる
if (!this.isWeaponTypeAllowed(unit.getClass().getEquipmentWeaponTypeReferenceList(), item)) {
return false;
}
// 「専用データ」を調べる
if (!this.isOnlyData(unit, item)) {
return false;
}
if (item.getWeaponCategoryType() === WeaponCategoryType.MAGIC) {
// 「魔法攻撃」が禁止されているか調べる
if (StateControl.isBadStateFlag(unit, BadStateFlag.MAGIC)) {
return false;
}
}
else {
// 「物理攻撃」が禁止されているか調べる
if (StateControl.isBadStateFlag(unit, BadStateFlag.PHYSICS)) {
return false;
}
}
return true;
},
// unitがアイテムを使用できるか調べる
isItemUsable: function(unit, item) {
// 武器は使用できない
if (item.isWeapon()) {
return false;
}
// アイテムの使用が禁止されているか調べる
if (StateControl.isBadStateFlag(unit, BadStateFlag.ITEM)) {
return false;
}
if (item.isWand()) {
// アイテムが杖の場合は、クラスが杖を使用できなければならない
if (!(unit.getClass().getClassOption() & ClassOptionFlag.WAND)) {
return false;
}
// 杖の使用が禁止されているか調べる
if (StateControl.isBadStateFlag(unit, BadStateFlag.WAND)) {
return false;
}
}
if (item.getItemType() === ItemType.KEY) {
if (item.getKeyInfo().isAdvancedKey()) {
// 「高度な鍵」の場合は、クラスが鍵を使用できなければならない
if (!(unit.getClass().getClassOption() & ClassOptionFlag.KEY)) {
return false;
}
}
}
// 「専用データ」を調べる
if (!this.isOnlyData(unit, item)) {
return false;
}
return true;
},
// 「専用データ」を調べる
isOnlyData: function(unit, item) {
// 「専用データ」にスキルが指定されている場合は、武器のスキルも調べる必要があるが、
// その武器を第2引数に指定することでループするのを防ぐ。
return item.getAvailableAggregation().isConditionFromWeapon(unit, item);
},
// 特効かどうかを調べる
isEffectiveData: function(unit, item) {
var aggregation = item.getEffectiveAggregation();
if (aggregation.getObjectCount() === 0) {
return false;
}
return aggregation.isCondition(unit);
},
// unitが所持しているアイテムから、flagを含む鍵アイテムを取得する
getKeyItem: function(unit, flag) {
var i, item, info, isKey;
var count = UnitItemControl.getPossessionItemCount(unit);
// アイテムを順番に調べる。
// 前方のアイテムほど優先される。
for (i = 0; i < count; i++) {
item = UnitItemControl.getItem(unit, i);
if (item === null) {
continue;
}
if (!item.isWeapon() && item.getItemType() === ItemType.KEY && this.isItemUsable(unit, item)) {
isKey = false;
info = item.getKeyInfo();
// 杖の場合はアイテムを返さない
if (!item.isWand()) {
if (info.getKeyFlag() & flag) {
isKey = true;
}
else {
isKey = false;
}
}
if (isKey) {
return item;
}
}
}
return null;
},
// itemとtargetItemが同一種類かどうか調べる
compareItem: function(item, targetItem) {
var id, targetId;
if (item === null || targetItem === null) {
return false;
}
id = item.getId();
targetId = targetItem.getId();
if (!item.isWeapon()) {
id += ItemIdValue.BASE;
}
if (!targetItem.isWeapon()) {
targetId += ItemIdValue.BASE;
}
// 通常、データのidはそれぞれ唯一の値である。
// ただし、同じアイテムは同じIDを持つため、以下の判定は有効である。
return id === targetId;
},
_isWeaponLevel: function(unit, item) {
// ParamBonus.getWlvを呼び出すとループする
return ParamBonus.getBonusFromWeapon(unit, ParamType.WLV, item) >= item.getWeaponLevel();
},
_compareTemplateAndCategory: function(unit, item) {
var result = false;
var classMotionFlag = unit.getClass().getClassMotionFlag();
var weaponCategoryType = item.getWeaponCategoryType();
// クラスの「戦士系」、「弓兵系」、「魔道士系」の全てが空白である場合は、
// 全ての武器を装備できる。
if (classMotionFlag === 0) {
return true;
}
if (weaponCategoryType === WeaponCategoryType.PHYSICS) {
if (classMotionFlag & ClassMotionFlag.FIGHTER) {
result = true;
}
}
else if (weaponCategoryType === WeaponCategoryType.SHOOT) {
if (classMotionFlag & ClassMotionFlag.ARCHER) {
result = true;
}
}
else if (weaponCategoryType === WeaponCategoryType.MAGIC) {
if (classMotionFlag & ClassMotionFlag.MARGE) {
result = true;
}
}
return result;
},
// 後のバージョンで削除
_isWeaponTypeAllowed: function(unit, item) {
return false;
},
// 後のバージョンで削除
_isOnlyData: function(unit, item) {
return false;
},
// 後のバージョンで削除
_isOnlyDataClass: function(cls, item) {
return false;
}
};
// unit.getItemなどの呼び出しをラッピングする
var UnitItemControl = {
getItem: function(unit, index) {
return unit.getItem(index);
},
setItem: function(unit, index, item) {
unit.setItem(index, item);
},
cutItem: function(unit, index) {
var item;
// clearItemは、indexが示すアイテム位置はnullにする。
// 戻り値は、以前に存在していたアイテム。
item = unit.clearItem(index);
this.arrangeItem(unit);
return item;
},
// アイテムの順番を整頓する
arrangeItem: function(unit) {
var i, j, item;
var count = this.getPossessionItemCount(unit);
var maxCount = DataConfig.getMaxUnitItemCount();
// 間に空白ができないようにアイテムを詰める
for (i = 0; i < count; i++) {
if (unit.getItem(i) === null) {
for (j = i + 1; j < maxCount; j++) {
item = unit.getItem(j);
if (item !== null) {
unit.setItem(i, item);
unit.clearItem(j);
break;
}
}
}
}
},
// unitのアイテム欄にitemを追加する
pushItem: function(unit, item) {
var count = this.getPossessionItemCount(unit);
if (count < DataConfig.getMaxUnitItemCount()) {
this.arrangeItem(unit);
unit.setItem(count, item);
return true;
}
return false;
},
// unitが所持しているアイテムの数を返す
getPossessionItemCount: function(unit) {
var i;
var count = DataConfig.getMaxUnitItemCount();
var bringCount = 0;
for (i = 0; i < count; i++) {
if (unit.getItem(i) !== null) {
bringCount++;
}
}
return bringCount;
},
// アイテムを追加できるスペースがあるか調べる
isUnitItemSpace: function(unit) {
return this.getPossessionItemCount(unit) !== DataConfig.getMaxUnitItemCount();
},
getMatchItem: function(unit, targetItem) {
var i, item, count;
if (unit === null) {
return null;
}
count = this.getPossessionItemCount(unit);
// targetItemをunitが所持しているかを調べる
for (i = 0; i < count; i++) {
item = this.getItem(unit, i);
if (item === targetItem) {
return item;
}
}
// 所持していない場合は、同一IDのアイテムを所持しているかを調べる
for (i = 0; i < count; i++) {
item = this.getItem(unit, i);
if (ItemControl.compareItem(item, targetItem)) {
return item;
}
}
return null;
},
getIndexFromItem: function(unit, targetItem) {
var i, item;
var count = UnitItemControl.getPossessionItemCount(unit);
for (i = 0; i < count; i++) {
item = UnitItemControl.getItem(unit, i);
if (item === targetItem) {
return i;
}
}
return -1;
}
};
// root.getMetaSession().getStockItemArrayの呼び出しをラッピングする
var StockItemControl = {
getStockItemArray: function() {
return root.getMetaSession().getStockItemArray();
},
getStockItem: function(index) {
var itemArray = this.getStockItemArray();
return itemArray[index];
},
setStockItem: function(index, item) {
var itemArray = this.getStockItemArray();
itemArray[index] = item;
this.sortItem();
},
pushStockItem: function(item) {
var itemArray = this.getStockItemArray();
itemArray.push(item);
this.sortItem();
},
cutStockItem: function(index) {
var itemArray = this.getStockItemArray();
itemArray.splice(index, 1);
this.sortItem();
},
getStockItemCount: function() {
var itemArray = this.getStockItemArray();
return itemArray.length;
},
isStockItemSpace: function() {
return this.getStockItemCount() !== DataConfig.getMaxStockItemCount();
},
getMatchItem: function(targetItem) {
var i, item;
var count = this.getStockItemCount();
for (i = 0; i < count; i++) {
item = this.getStockItem(i);
if (ItemControl.compareItem(item, targetItem)) {
return item;
}
}
return null;
},
getIndexFromItem: function(item) {
var i;
var count = this.getStockItemCount();
for (i = 0; i < count; i++) {
if (this.getStockItem(i) === item) {
return i;
}
}
return -1;
},
sortItem: function() {
var itemArray = this.getStockItemArray();
// 並び替えの優先順位は次のようになる。
// ・武器はアイテムより優先
// ・idが低いアイテムは高いアイテムより優先
// ・耐久が低いアイテムは高いアイテムより優先
itemArray.sort(
function(item1, item2) {
var id1, id2;
var limit1, limit2;
id1 = item1.getId();
id2 = item2.getId();
if (!item1.isWeapon()) {
id1 += ItemIdValue.BASE;
}
if (!item2.isWeapon()) {
id2 += ItemIdValue.BASE;
}
if (id1 > id2) {
return 1;
}
else if (id1 < id2) {
return -1;
}
else {
limit1 = item1.getLimit();
limit2 = item2.getLimit();
if (limit1 > limit2) {
return 1;
}
else if (limit1 < limit2) {
return -1;
}
}
return 0;
}
);
}
};
var ItemChangeControl = {
changeStockItem: function(targetItem, increaseType) {
var arr = [];
// arrにアイテムが格納された場合は、そのアイテムはストックに格納できない
if (increaseType === IncreaseType.INCREASE) {
arr = this._increaseStockItem(targetItem);
}
else if (increaseType === IncreaseType.DECREASE) {
arr = this._decreaseStockItem(targetItem);
}
else if (increaseType === IncreaseType.ALLRELEASE) {
arr = this._releaseAllStockItem();
}
return arr;
},
changeUnitItem: function(unit, targetItem, increaseType, isStockSend) {
var arr = [];
// arrにアイテムが格納された場合は、そのアイテムは所持またはストックに格納できない
if (increaseType === IncreaseType.INCREASE) {
arr = this._increaseUnitItem(unit, targetItem);
}
else if (increaseType === IncreaseType.DECREASE) {
arr = this._decreaseUnitItem(unit, targetItem, isStockSend);
}
else if (increaseType === IncreaseType.ALLRELEASE) {
arr = this._releaseAllUnitItem(unit, isStockSend);
}
return arr;
},
_increaseStockItem: function(targetItem) {
var arr = [];
if (!StockItemControl.isStockItemSpace()) {
arr.push(targetItem);
return arr;
}
StockItemControl.pushStockItem(targetItem);
return arr;
},
_decreaseStockItem: function(targetItem) {
var i, item;
var count = StockItemControl.getStockItemCount();
for (i = 0; i < count; i++) {
item = StockItemControl.getStockItem(i);
if (item !== null && ItemControl.compareItem(item, targetItem)) {
StockItemControl.cutStockItem(i);
break;
}
}
return [];
},
_releaseAllStockItem: function() {
var i;
var count = StockItemControl.getStockItemCount();
// 重要アイテムも含めて全て削除される
for (i = 0; i < count; i++) {
StockItemControl.cutStockItem(0);
}
return [];
},
_increaseUnitItem: function(unit, targetItem) {
var arr = [];
if (!UnitItemControl.isUnitItemSpace(unit)) {
arr.push(targetItem);
return arr;
}
UnitItemControl.pushItem(unit, targetItem);
// 新しいアイテムを所持したため更新
ItemControl.updatePossessionItem(unit);
return arr;
},
_decreaseUnitItem: function(unit, targetItem, isStockSend) {
var i, item, curItem;
var count = DataConfig.getMaxUnitItemCount();
var arr = [];
for (i = 0; i < count; i++) {
item = UnitItemControl.getItem(unit, i);
if (ItemControl.compareItem(item, targetItem)) {
// 同じアイテムが見つかったから消去
curItem = UnitItemControl.cutItem(unit, i);
if (curItem !== null && isStockSend) {
if (StockItemControl.isStockItemSpace()) {
StockItemControl.pushStockItem(curItem);
}
else {
arr.push(curItem);
}
}
break;
}
}
return arr;
},
_releaseAllUnitItem: function(unit, isStockSend) {
var i, curItem;
var count = DataConfig.getMaxUnitItemCount();
var arr = [];
for (i = 0; i < count; i++) {
curItem = UnitItemControl.cutItem(unit, 0);
if (curItem !== null && isStockSend) {
if (StockItemControl.isStockItemSpace()) {
StockItemControl.pushStockItem(curItem);
}
else {
arr.push(curItem);
}
}
}
return arr;
}
};