Anton Tarasenko
3 years ago
10 changed files with 1241 additions and 1 deletions
@ -0,0 +1,417 @@
|
||||
/** |
||||
* Player's inventory implementation for classic Killing Floor that changes |
||||
* as little as possible and only on request from another mod, otherwise not |
||||
* altering gameplay at all. |
||||
* Copyright 2021 Anton Tarasenko |
||||
*------------------------------------------------------------------------------ |
||||
* This file is part of Acedia. |
||||
* |
||||
* Acedia is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* Acedia is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
||||
*/ |
||||
class EKFInventory extends EInventory |
||||
config(AcediaSystem_KF1Frontend); |
||||
|
||||
struct DualiesPair |
||||
{ |
||||
var class<KFWeaponPickup> single; |
||||
var class<KFWeaponPickup> dual; |
||||
}; |
||||
|
||||
var private APlayer inventoryOwner; |
||||
var private config array<DualiesPair> dualiesClasses; |
||||
|
||||
protected function Finalizer() |
||||
{ |
||||
inventoryOwner = none; |
||||
} |
||||
|
||||
public function Initialize(APlayer player) |
||||
{ |
||||
if (inventoryOwner != none) { |
||||
return; |
||||
} |
||||
inventoryOwner = player; |
||||
} |
||||
|
||||
private function Pawn GetOwnerPawn() |
||||
{ |
||||
local PlayerService service; |
||||
service = PlayerService(class'PlayerService'.static.Require()); |
||||
if (service == none) { |
||||
return none; |
||||
} |
||||
return service.GetPawn(inventoryOwner); |
||||
} |
||||
|
||||
public function bool Add(EItem newItem, optional bool forceAddition) |
||||
{ |
||||
local Pawn pawn; |
||||
local EKFWeapon kfWeaponItem; |
||||
local KFWeapon kfWeapon; |
||||
if (!CanAdd(newItem, forceAddition)) return false; |
||||
kfWeaponItem = EKFWeapon(newItem); |
||||
if (kfWeaponItem == none) return false; |
||||
pawn = GetOwnerPawn(); |
||||
if (pawn == none) return false; |
||||
kfWeapon = kfWeaponItem.GetNativeInstance(); |
||||
if (kfWeapon == none) return false; |
||||
|
||||
kfWeapon.GiveTo(pawn); |
||||
return true; |
||||
} |
||||
|
||||
public function bool AddTemplate( |
||||
Text newItemTemplate, |
||||
optional bool forceAddition) |
||||
{ |
||||
local Pawn pawn; |
||||
local KFWeapon newWeapon; |
||||
if (newItemTemplate == none) return false; |
||||
if (!CanAddTemplate(newItemTemplate, forceAddition)) return false; |
||||
pawn = GetOwnerPawn(); |
||||
if (pawn == none) return false; |
||||
|
||||
newWeapon = KFWeapon(_.memory.AllocateByReference(newItemTemplate)); |
||||
if (newWeapon != none) |
||||
{ |
||||
_.unreal.GetKFGameType().WeaponSpawned(newWeapon); |
||||
newWeapon.GiveTo(pawn); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public function bool CanAdd(EItem itemToCheck, optional bool forceAddition) |
||||
{ |
||||
local EKFWeapon kfWeaponItem; |
||||
local KFWeapon kfWeapon; |
||||
kfWeaponItem = EKFWeapon(itemToCheck); |
||||
if (kfWeaponItem == none) return false; // can only add weapons |
||||
kfWeapon = kfWeaponItem.GetNativeInstance(); |
||||
if (kfWeapon == none) return false; // dead `EKFWeapon` object |
||||
|
||||
return CanAddWeaponClass(kfWeapon.class, forceAddition); |
||||
} |
||||
|
||||
public function bool CanAddTemplate( |
||||
Text itemTemplateToCheck, |
||||
optional bool forceAddition) |
||||
{ |
||||
local class<KFWeapon> kfWeaponClass; |
||||
// Can only add weapons for now |
||||
kfWeaponClass = class<KFWeapon>(_.memory.LoadClass(itemTemplateToCheck)); |
||||
return CanAddWeaponClass(kfWeaponClass, forceAddition); |
||||
} |
||||
|
||||
public function bool CanAddWeaponClass( |
||||
class<KFWeapon> kfWeaponClass, |
||||
optional bool forceAddition) |
||||
{ |
||||
local KFPawn kfPawn; |
||||
if (kfWeaponClass == none) return false; |
||||
kfPawn = KFPawn(GetOwnerPawn()); |
||||
if (kfPawn == none) return false; |
||||
|
||||
if (!forceAddition && !kfPawn.CanCarry(kfWeaponClass.default.weight)) { |
||||
return false; |
||||
} |
||||
if (kfPawn.FindInventoryType(kfWeaponClass) != none) { |
||||
return false; |
||||
} |
||||
if (!forceAddition && HasSameTypeWeapons(kfWeaponClass, kfPawn)) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
private function bool HasSameTypeWeapons( |
||||
class<KFWeapon> kfWeaponClass, |
||||
Pawn pawn) |
||||
{ |
||||
local Inventory nextInventory; |
||||
local class<KFWeaponPickup> itemRoot, nextRoot; |
||||
nextInventory = pawn.inventory; |
||||
itemRoot = GetRootPickupClass(kfWeaponClass); |
||||
while (nextInventory != none) |
||||
{ |
||||
nextRoot = GetRootPickupClass(class<KFWeapon>(nextInventory.class)); |
||||
if (itemRoot == nextRoot) { |
||||
return true; |
||||
} |
||||
nextInventory = nextInventory.inventory; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
// Returns a root pickup class. |
||||
// For non-dual weapons, root class is defined as either: |
||||
// 1. the first variant (reskin), if there are variants for that weapon; |
||||
// 2. and as the class itself, if there are no variants. |
||||
// For dual weapons (all dual pistols) root class is defined as |
||||
// a root of their single version. |
||||
// This definition is useful because: |
||||
// ~ Vanilla game rules are such that player can only have two weapons |
||||
// in the inventory if they have different roots; |
||||
// ~ Root is easy to find. |
||||
private final function class<KFWeaponPickup> GetRootPickupClass( |
||||
class<KFWeapon> weapon) |
||||
{ |
||||
local int i; |
||||
local class<KFWeaponPickup> root; |
||||
if (weapon == none) return none; |
||||
// Start with a pickup of the given weapons |
||||
root = class<KFWeaponPickup>(weapon.default.pickupClass); |
||||
if (root == none) return none; |
||||
|
||||
// In case it's a dual version - find corresponding single pickup class |
||||
// (it's root would be the same). |
||||
for (i = 0; i < dualiesClasses.length; i += 1) |
||||
{ |
||||
if (dualiesClasses[i].dual == root) |
||||
{ |
||||
root = dualiesClasses[i].single; |
||||
break; |
||||
} |
||||
} |
||||
// Take either first variant class or the class itself, - |
||||
// it's going to be root by definition. |
||||
if (root.default.variantClasses.length > 0) { |
||||
root = class<KFWeaponPickup>(root.default.variantClasses[0]); |
||||
} |
||||
return root; |
||||
} |
||||
|
||||
public function bool Remove( |
||||
EItem itemToRemove, |
||||
optional bool keepItem, |
||||
optional bool forceRemoval) |
||||
{ |
||||
local bool removedItem; |
||||
local float passedTime; |
||||
local Pawn pawn; |
||||
local Inventory nextInventory; |
||||
local EKFWeapon kfWeaponItem; |
||||
local KFWeapon kfWeapon; |
||||
kfWeaponItem = EKFWeapon(itemToRemove); |
||||
if (kfWeaponItem == none) return false; |
||||
pawn = GetOwnerPawn(); |
||||
if (pawn == none) return false; |
||||
if (pawn.inventory == none) return false; |
||||
kfWeapon = kfWeaponItem.GetNativeInstance(); |
||||
if (kfWeapon == none) return false; |
||||
if (!forceRemoval && kfWeapon.bKFNeverThrow) return false; |
||||
|
||||
passedTime = _.unreal.GetLevel().timeSeconds - 1; |
||||
nextInventory = pawn.inventory; |
||||
while (nextInventory.inventory != none) |
||||
{ |
||||
if (nextInventory.inventory == kfWeapon) |
||||
{ |
||||
nextInventory.inventory = kfWeapon.inventory; |
||||
kfWeapon.inventory = none; |
||||
nextInventory.netUpdateTime = passedTime; |
||||
kfWeapon.netUpdateTime = passedTime; |
||||
kfWeapon.Destroy(); |
||||
removedItem = true; |
||||
} |
||||
else { |
||||
nextInventory = nextInventory.inventory; |
||||
} |
||||
} |
||||
return removedItem; |
||||
} |
||||
|
||||
public function bool RemoveTemplate( |
||||
Text itemTemplateToRemove, |
||||
optional bool keepItem, |
||||
optional bool forceRemoval, |
||||
optional bool removeAll) |
||||
{ |
||||
local bool canRemoveInventory; |
||||
local bool removedItem; |
||||
local float passedTime; |
||||
local Pawn pawn; |
||||
local Inventory nextInventory; |
||||
local KFWeapon nextKFWeapon; |
||||
local class<KFWeapon> kfWeaponClass; |
||||
pawn = GetOwnerPawn(); |
||||
if (pawn == none) return false; |
||||
if (pawn.inventory == none) return false; |
||||
kfWeaponClass = class<KFWeapon>(_.memory.LoadClass(itemTemplateToRemove)); |
||||
if (kfWeaponClass == none) return false; |
||||
if (!forceRemoval && kfWeaponClass.default.bKFNeverThrow) return false; |
||||
|
||||
passedTime = _.unreal.GetLevel().timeSeconds - 1; |
||||
nextInventory = pawn.inventory; |
||||
while (nextInventory.inventory != none) |
||||
{ |
||||
canRemoveInventory = true; |
||||
if (!forceRemoval) |
||||
{ |
||||
nextKFWeapon = KFWeapon(nextInventory.inventory); |
||||
if (nextKFWeapon != none && nextKFWeapon.bKFNeverThrow) { |
||||
canRemoveInventory = false; |
||||
} |
||||
} |
||||
if ( canRemoveInventory |
||||
&& nextInventory.inventory.class == kfWeaponClass) |
||||
{ |
||||
nextInventory.inventory = nextKFWeapon.inventory; |
||||
nextKFWeapon.inventory = none; |
||||
nextInventory.netUpdateTime = passedTime; |
||||
nextKFWeapon.netUpdateTime = passedTime; |
||||
nextKFWeapon.Destroy(); |
||||
removedItem = true; |
||||
if (!removeAll) { |
||||
return true; |
||||
} |
||||
} |
||||
else { |
||||
nextInventory = nextInventory.inventory; |
||||
} |
||||
} |
||||
return removedItem; |
||||
} |
||||
|
||||
public function bool RemoveAll( |
||||
optional bool keepItems, |
||||
optional bool forceRemoval) |
||||
{ |
||||
local int i; |
||||
local Pawn pawn; |
||||
local KFWeapon kfWeapon; |
||||
local Inventory nextInventory; |
||||
local class<Weapon> destroyedClass; |
||||
local array<Inventory> inventoryToRemove; |
||||
pawn = GetOwnerPawn(); |
||||
if (pawn == none) return false; |
||||
if (pawn.inventory == none) return false; |
||||
|
||||
nextInventory = pawn.inventory; |
||||
while (nextInventory != none) |
||||
{ |
||||
kfWeapon = KFWeapon(nextInventory); |
||||
if (kfWeapon == none) |
||||
{ |
||||
nextInventory = nextInventory.inventory; |
||||
continue; // TODO: handle non-weapons differently |
||||
} |
||||
if (forceRemoval || !kfWeapon.bKFNeverThrow) { |
||||
inventoryToRemove[inventoryToRemove.length] = nextInventory; |
||||
} |
||||
nextInventory = nextInventory.inventory; |
||||
} |
||||
for(i = 0; i < inventoryToRemove.length; i += 1) |
||||
{ |
||||
if (inventoryToRemove[i] == none) { |
||||
continue; |
||||
} |
||||
destroyedClass = class<Weapon>(inventoryToRemove[i].class); |
||||
inventoryToRemove[i].Destroyed(); |
||||
inventoryToRemove[i].Destroy(); |
||||
_.unreal.GetKFGameType().WeaponDestroyed(destroyedClass); |
||||
} |
||||
return (inventoryToRemove.length > 0); |
||||
} |
||||
|
||||
/** |
||||
* Checks whether caller `EInventory` contains given `itemToCheck`. |
||||
* |
||||
* @param itemToCheck `EItem` we want to check for belonging to the caller |
||||
* `EInventory`. |
||||
* @result `true` if item does belong to the inventory and `false` otherwise. |
||||
*/ |
||||
public function bool Contains(EItem itemToCheck) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns array with all `EItem`s contained inside the caller `EInventory`. |
||||
* |
||||
* @return Array with all `EItem`s contained inside the caller `EInventory`. |
||||
*/ |
||||
public function array<EItem> GetAllItems() |
||||
{ |
||||
local array<EItem> emptyArray; |
||||
return emptyArray; |
||||
} |
||||
|
||||
/** |
||||
* Returns array with all `EItem`s contained inside the caller `EInventory` |
||||
* that has specified tag `tag`. |
||||
* |
||||
* @param tag Tag, which items we want to get. |
||||
* @return Array with all `EItem`s contained inside the caller `EInventory` |
||||
* that has specified tag `tag`. |
||||
*/ |
||||
public function array<EItem> GetTagItems(Text tag) |
||||
{ |
||||
local array<EItem> emptyArray; |
||||
return emptyArray; |
||||
} |
||||
|
||||
/** |
||||
* Returns `EItem` contained inside the caller `EInventory` that has specified |
||||
* tag `tag`. |
||||
* |
||||
* If several `EItem`s inside caller `EInventory` have specified tag, |
||||
* inventory system can pick one arbitrarily (can be based on simple |
||||
* convenience of implementation). Returned value does not have to |
||||
* be stable (the same after repeated calls). |
||||
* |
||||
* @param tag Tag, which item we want to get. |
||||
* @return `EItem` contained inside the caller `EInventory` that belongs to |
||||
* the specified tag `tag`. |
||||
*/ |
||||
public function EItem GetTagItem(Text tag) { return none; } |
||||
|
||||
/** |
||||
* Returns array with all `EItem`s contained inside the caller `EInventory` |
||||
* that originated from the specified template `template`. |
||||
* |
||||
* @param template Template, that items we want to get originated from. |
||||
* @return Array with all `EItem`s contained inside the caller `EInventory` |
||||
* that originated from the specified template `template`. |
||||
*/ |
||||
public function array<EItem> GetTemplateItems(Text template) |
||||
{ |
||||
local array<EItem> emptyArray; |
||||
return emptyArray; |
||||
} |
||||
|
||||
/** |
||||
* Returns array with all `EItem`s contained inside the caller `EInventory` |
||||
* that originated from the specified template `template`. |
||||
* |
||||
* If several `EItem`s inside caller `EInventory` originated from |
||||
* that template, inventory system can pick one arbitrarily (can be based on |
||||
* simple convenience of implementation). Returned value does not have to |
||||
* be stable (the same after repeated calls). |
||||
* |
||||
* @param template Template, that item we want to get originated from. |
||||
* @return `EItem`s contained inside the caller `EInventory` that originated |
||||
* from the specified template `template`. |
||||
*/ |
||||
public function EItem GetTemplateItem(Text template) { return none; } |
||||
|
||||
defaultproperties |
||||
{ |
||||
dualiesClasses(0)=(single=class'KFMod.SinglePickup',dual=class'KFMod.DualiesPickup') |
||||
dualiesClasses(1)=(single=class'KFMod.Magnum44Pickup',dual=class'KFMod.Dual44MagnumPickup') |
||||
dualiesClasses(2)=(single=class'KFMod.MK23Pickup',dual=class'KFMod.DualMK23Pickup') |
||||
dualiesClasses(3)=(single=class'KFMod.DeaglePickup',dual=class'KFMod.DualDeaglePickup') |
||||
dualiesClasses(4)=(single=class'KFMod.GoldenDeaglePickup',dual=class'KFMod.GoldenDualDeaglePickup') |
||||
dualiesClasses(5)=(single=class'KFMod.FlareRevolverPickup',dual=class'KFMod.DualFlareRevolverPickup') |
||||
} |
@ -0,0 +1,81 @@
|
||||
/** |
||||
* Implementation of `EKFItemTemplateInfo` for classic Killing Floor items that |
||||
* changes as little as possible and only on request from another mod, |
||||
* otherwise not altering gameplay at all. |
||||
* Copyright 2021 Anton Tarasenko |
||||
*------------------------------------------------------------------------------ |
||||
* This file is part of Acedia. |
||||
* |
||||
* Acedia is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* Acedia is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
||||
*/ |
||||
class EKFItemTemplateInfo extends EItemTemplateInfo; |
||||
|
||||
var private class<Inventory> classReference; |
||||
|
||||
/** |
||||
* Creates new `EKFItemTemplateInfo` that refers to the `newClass` inventory |
||||
* class. |
||||
* |
||||
* @param newClass Native inventory class that new `EKFItemTemplateInfo` |
||||
* will represent. |
||||
* @return New `EKFItemTemplateInfo` that represents given `newClass`. |
||||
*/ |
||||
public final static function EKFItemTemplateInfo Wrap( |
||||
class<Inventory> newInventoryClass) |
||||
{ |
||||
local EKFItemTemplateInfo newTemplateReference; |
||||
if (newInventoryClass == none) { |
||||
return none; |
||||
} |
||||
newTemplateReference = |
||||
EKFItemTemplateInfo(__().memory.Allocate(class'EKFItemTemplateInfo')); |
||||
newTemplateReference.classReference = newInventoryClass; |
||||
return newTemplateReference; |
||||
} |
||||
|
||||
public function array<Text> GetTags() |
||||
{ |
||||
local array<Text> tagArray; |
||||
if (class<Weapon>(classReference) != none) { |
||||
tagArray[0] = P("weapon").Copy(); |
||||
} |
||||
return tagArray; |
||||
} |
||||
|
||||
public function Text GetTemplateName() |
||||
{ |
||||
if (classReference == none) { |
||||
return none; |
||||
} |
||||
return _.text.FromString(Locs(string(classReference))); |
||||
} |
||||
|
||||
public function Text GetName() |
||||
{ |
||||
local class<KFWeaponPickup> pickupClass; |
||||
if (classReference == none) { |
||||
return none; |
||||
} |
||||
// `KFWeaponPickup` names are usually longer and an overall better fit for |
||||
// being displayed |
||||
pickupClass = class<KFWeaponPickup>(classReference.default.pickupClass); |
||||
if (pickupClass != none && pickupClass.default.itemName != "") { |
||||
return _.text.FromString(pickupClass.default.itemName); |
||||
} |
||||
return _.text.FromString(classReference.default.itemName); |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
@ -0,0 +1,150 @@
|
||||
/** |
||||
* Implementation of `EItem` for classic Killing Floor weapons that changes |
||||
* as little as possible and only on request from another mod, otherwise not |
||||
* altering gameplay at all. |
||||
* Copyright 2021 Anton Tarasenko |
||||
*------------------------------------------------------------------------------ |
||||
* This file is part of Acedia. |
||||
* |
||||
* Acedia is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* Acedia is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
||||
*/ |
||||
class EKFWeapon extends EItem |
||||
abstract; |
||||
|
||||
var private NativeActorRef weaponReference; |
||||
|
||||
protected function Finalizer() |
||||
{ |
||||
_.memory.Free(weaponReference); |
||||
weaponReference = none; |
||||
} |
||||
|
||||
/** |
||||
* Creates new `EKFWeapon` that refers to the `weaponInstance` weapon. |
||||
* |
||||
* @param weaponInstance Native weapon class that new `EKFWeapon` will |
||||
* represent. |
||||
* @return New `EKFWeapon` that represents given `weaponInstance`. |
||||
*/ |
||||
public final static function EKFWeapon Make(KFWeapon weaponInstance) |
||||
{ |
||||
local EKFWeapon newReference; |
||||
newReference = EKFWeapon(__().memory.Allocate(class'EKFWeapon')); |
||||
newReference.weaponReference = __().unreal.ActorRef(weaponInstance); |
||||
return newReference; |
||||
} |
||||
|
||||
/** |
||||
* Returns `KFWeapon` instance represented by the caller `EKFWeapon`. |
||||
* |
||||
* @return `KFWeapon` instance represented by the caller `EKFWeapon`. |
||||
*/ |
||||
public final function KFWeapon GetNativeInstance() |
||||
{ |
||||
if (weaponReference != none) { |
||||
return KFWeapon(weaponReference.Get()); |
||||
} |
||||
return none; |
||||
} |
||||
|
||||
public function array<Text> GetTags() |
||||
{ |
||||
local array<Text> tagArray; |
||||
if (weaponReference == none) return tagArray; |
||||
if (weaponReference.Get() == none) return tagArray; |
||||
|
||||
tagArray[0] = P("weapon").Copy(); |
||||
return tagArray; |
||||
} |
||||
|
||||
public function Text GetTemplate() |
||||
{ |
||||
local Weapon weapon; |
||||
if (weaponReference == none) return none; |
||||
weapon = Weapon(weaponReference.Get()); |
||||
if (weapon == none) return none; |
||||
|
||||
return _.text.FromString(Locs(string(weapon.class))); |
||||
} |
||||
|
||||
public function Text GetName() |
||||
{ |
||||
local Weapon weapon; |
||||
if (weaponReference == none) return none; |
||||
weapon = Weapon(weaponReference.Get()); |
||||
if (weapon == none) return none; |
||||
|
||||
return _.text.FromString(Locs(weapon.itemName)); |
||||
} |
||||
|
||||
public function bool IsRemovable() |
||||
{ |
||||
local KFWeapon kfWeapon; // Check is only meaningful for `KFWeapon`s |
||||
if (weaponReference == none) return false; |
||||
kfWeapon = KFWeapon(weaponReference.Get()); |
||||
if (kfWeapon == none) return false; |
||||
|
||||
return !kfWeapon.bKFNeverThrow; |
||||
} |
||||
|
||||
public function bool IsSellable() |
||||
{ |
||||
return IsRemovable(); |
||||
} |
||||
|
||||
public function bool SetPrice(int newPrice) |
||||
{ |
||||
local KFWeapon kfWeapon; // Price is only meaningful for `KFWeapon`s |
||||
if (weaponReference == none) return false; |
||||
kfWeapon = KFWeapon(weaponReference.Get()); |
||||
if (kfWeapon == none) return false; |
||||
|
||||
kfWeapon.sellValue = newPrice; |
||||
return true; |
||||
} |
||||
|
||||
public function int GetPrice() |
||||
{ |
||||
local KFWeapon kfWeapon; // Price is only meaningful for `KFWeapon`s |
||||
if (weaponReference == none) return 0; |
||||
kfWeapon = KFWeapon(weaponReference.Get()); |
||||
if (kfWeapon == none) return 0; |
||||
|
||||
return kfWeapon.sellValue; |
||||
} |
||||
|
||||
public function bool SetWeight(int newWeight) |
||||
{ |
||||
local KFWeapon kfWeapon; // Weight is only meaningful for `KFWeapon`s |
||||
if (weaponReference == none) return false; |
||||
kfWeapon = KFWeapon(weaponReference.Get()); |
||||
if (kfWeapon == none) return false; |
||||
|
||||
kfWeapon.weight = newWeight; |
||||
return true; |
||||
} |
||||
|
||||
public function int GetWeight() |
||||
{ |
||||
local KFWeapon kfWeapon; // Weight is only meaningful for `KFWeapon`s |
||||
if (weaponReference == none) return 0; |
||||
kfWeapon = KFWeapon(weaponReference.Get()); |
||||
if (kfWeapon == none) return 0; |
||||
|
||||
return int(kfWeapon.weight); |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
@ -0,0 +1,291 @@
|
||||
/** |
||||
* Abstract interface that represents inventory system. Inventory system is |
||||
* supposed to represent a way to handle items in players inventory - |
||||
* in Killing Floor it is a simple set of items with total weight limitations. |
||||
* But any other kind of inventory can be implemented as long as it follows |
||||
* limitations of this interface. |
||||
* Copyright 2021 Anton Tarasenko |
||||
*------------------------------------------------------------------------------ |
||||
* This file is part of Acedia. |
||||
* |
||||
* Acedia is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* Acedia is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
||||
*/ |
||||
class EInventory extends AcediaObject |
||||
abstract; |
||||
|
||||
/** |
||||
* Initializes `EInventory` for a given `player`. |
||||
* |
||||
* This method should not be called manually, unless you implement your own |
||||
* game interface. |
||||
* |
||||
* Cannot fail for any connected player and can assume it will not be called |
||||
* for not connected ones. |
||||
* |
||||
* @param player `APlayer` for which to initialize this inventory. |
||||
*/ |
||||
public function Initialize(APlayer player) {} |
||||
|
||||
/** |
||||
* Adds passed `EItem` to the caller inventory system. |
||||
* |
||||
* If adding `newItem` is not currently possible for the caller |
||||
* inventory system - it can refuse it. |
||||
* |
||||
* @param newItem New item to add to the caller inventory system. |
||||
* @param forceAddition This parameter is only relevant when `newItem` |
||||
* cannot be added in the caller inventory system. If it cannot be added |
||||
* because of the conflict with other items - setting this flag to `true` |
||||
* allows caller inventory system to get rid of such items to make room for |
||||
* `newItem`. Removing items is only allowed if it will actually let us add |
||||
* `newItem`. How removal will be done is up to the implementation. |
||||
* @return `true` if `newItem` was added and `false` otherwise. |
||||
*/ |
||||
public function bool Add(EItem newItem, optional bool forceAddition) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Adds new `EItem` of template `newItemTemplate` to the caller |
||||
* inventory system. |
||||
* |
||||
* If adding new item is not currently possible for the caller |
||||
* inventory system - it can refuse it. |
||||
* |
||||
* @param newItemTemplate Template of the new item to add to |
||||
* the caller inventory system. |
||||
* @param forceAddition This parameter is only relevant when new item |
||||
* cannot be added in the caller inventory system. If it cannot be added |
||||
* because of the conflict with other items - setting this flag to `true` |
||||
* allows caller inventory system to get rid of such items to make room for |
||||
* new item. Removing items is only allowed if it will actually let us add |
||||
* new item. How removal will be done is up to the implementation. |
||||
* @return `true` if new item was added and `false` otherwise. |
||||
*/ |
||||
public function bool AddTemplate( |
||||
Text newItemTemplate, |
||||
optional bool forceAddition) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Checks whether given item `itemToCheck` can be added to the caller |
||||
* inventory system. |
||||
* |
||||
* @param itemToCheck Item to check for whether we can add it to |
||||
* the caller `EInventory`. |
||||
* @param forceAddition New items can be added with or without |
||||
* `forceAddition` flag. This parameter allows you to check whether we |
||||
* test for addition with or without it. |
||||
* @return `true` if given `itemToCheck` can be added to the caller |
||||
* inventory system with given flag `forceAddition` and `false` otherwise. |
||||
*/ |
||||
public function bool CanAdd(EItem itemToCheck, optional bool forceAddition) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Checks whether item with given template `itemToCheck` can be added to |
||||
* the caller inventory system. |
||||
* |
||||
* @param itemTemplateToCheck Template of the item to check for whether we can |
||||
* add it to the caller `EInventory`. |
||||
* @param forceAddition New items can be added with or without |
||||
* `forceAddition` flag. This parameter allows you to check whether we |
||||
* test for addition with or without it. |
||||
* @return `true` if item with given template `itemTemplateToCheck` can be |
||||
* added to the caller inventory system with given flag `forceAddition` and |
||||
* `false` otherwise. |
||||
*/ |
||||
public function bool CanAddTemplate( |
||||
Text itemTemplateToCheck, |
||||
optional bool forceAddition) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Removes given item `itemToRemove` from the caller `EInventory`. |
||||
* |
||||
* Based on gameplay considerations, inventory system can refuse removing |
||||
* `EItem`s for which `IsRemovable()` returns `false`. But removal of any item |
||||
* can be enforced with optional third parameter. |
||||
* |
||||
* @param itemToRemove Item that needs to be removed. |
||||
* @param keepItem By default removed item is destroyed. |
||||
* Setting this flag to `true` will make caller `EInventory` try to |
||||
* preserve it in some way. For Killing Floor it means dropping the item. |
||||
* @param forceRemoval Set this to `true` if item must be removed |
||||
* no matter what. Otherwise inventory system can refuse removal of items, |
||||
* whose `IsRemovable()` returns `false`. |
||||
* @return `true` if `EItem` was removed and `false` otherwise |
||||
* (including the case where `EItem` was not kept in the caller |
||||
* `EInventory` in the first place). |
||||
*/ |
||||
public function bool Remove( |
||||
EItem itemToRemove, |
||||
optional bool keepItem, |
||||
optional bool forceRemoval) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Removes item of type `itemTemplateToRemove` from the caller `EInventory`. |
||||
* |
||||
* By default removes one arbitrary (can be based on simple convenience of |
||||
* implementation) item, but optional parameter can make it remove all items |
||||
* of that type. |
||||
* |
||||
* Based on gameplay considerations, inventory system can refuse removing any |
||||
* `EItem` if `IsRemovable()` returns `false` for all stored items of |
||||
* given type `itemTemplateToRemove`. But removal of any item can be enforced |
||||
* with optional third parameter. |
||||
* |
||||
* @param itemTemplateToRemove Type of item that needs to be removed. |
||||
* @param keepItem By default removed item is destroyed. |
||||
* Setting this flag to `true` will make caller `EInventory` try to |
||||
* preserve it in some way. For Killing Floor it means dropping the item. |
||||
* @param forceRemoval Set this to `true` if item must be removed |
||||
* no matter what. Otherwise inventory system can refuse removal if |
||||
* `IsRemovable()` returns `false` for all items of given type. |
||||
* @param removeAll Set this to `true` if all items of the given type |
||||
* must be removed from the caller `EInventory` and keep `false` to remove |
||||
* only one. With `forceRemoval == false` it is possible that only items |
||||
* that return `false` for `IsRemovable()` will be removed, while others |
||||
* will be retained. |
||||
* @return `true` if any `EItem`s was removed and `false` otherwise |
||||
* (including the case where `EItem` of given type were not kept in the |
||||
* caller `EInventory` in the first place). |
||||
*/ |
||||
public function bool RemoveTemplate( |
||||
Text itemTemplateToRemove, |
||||
optional bool keepItem, |
||||
optional bool forceRemoval, |
||||
optional bool removeAll) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Removes all items from the caller `EInventory`. |
||||
* |
||||
* Based on gameplay considerations, inventory system can refuse removing |
||||
* `EItem`s for which `IsRemovable()` returns `false`. But removal of any item |
||||
* can be enforced with optional second parameter. |
||||
* |
||||
* @param keepItem By default removed item is destroyed. |
||||
* Setting this flag to `true` will make caller `EInventory` try to |
||||
* preserve it in some way. For Killing Floor it means dropping the item. |
||||
* @param forceRemoval Set this to `true` if item must be removed |
||||
* no matter what. Otherwise inventory system can refuse removal of items, |
||||
* whose `IsRemovable()` returns `false`. |
||||
* @return `true` if any `EItem` was removed and `false` otherwise |
||||
* (including the case where no `EItem`s were kept in the caller |
||||
* `EInventory` in the first place). |
||||
*/ |
||||
public function bool RemoveAll( |
||||
optional bool keepItems, |
||||
optional bool forceRemoval) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Checks whether caller `EInventory` contains given `itemToCheck`. |
||||
* |
||||
* @param itemToCheck `EItem` we want to check for belonging to the caller |
||||
* `EInventory`. |
||||
* @result `true` if item does belong to the inventory and `false` otherwise. |
||||
*/ |
||||
public function bool Contains(EItem itemToCheck) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns array with all `EItem`s contained inside the caller `EInventory`. |
||||
* |
||||
* @return Array with all `EItem`s contained inside the caller `EInventory`. |
||||
*/ |
||||
public function array<EItem> GetAllItems() |
||||
{ |
||||
local array<EItem> emptyArray; |
||||
return emptyArray; |
||||
} |
||||
|
||||
/** |
||||
* Returns array with all `EItem`s contained inside the caller `EInventory` |
||||
* that has specified tag `tag`. |
||||
* |
||||
* @param tag Tag, which items we want to get. |
||||
* @return Array with all `EItem`s contained inside the caller `EInventory` |
||||
* that has specified tag `tag`. |
||||
*/ |
||||
public function array<EItem> GetTagItems(Text tag) |
||||
{ |
||||
local array<EItem> emptyArray; |
||||
return emptyArray; |
||||
} |
||||
|
||||
/** |
||||
* Returns `EItem` contained inside the caller `EInventory` that has specified |
||||
* tag `tag`. |
||||
* |
||||
* If several `EItem`s inside caller `EInventory` have specified tag, |
||||
* inventory system can pick one arbitrarily (can be based on simple |
||||
* convenience of implementation). Returned value does not have to |
||||
* be stable (the same after repeated calls). |
||||
* |
||||
* @param tag Tag, which item we want to get. |
||||
* @return `EItem` contained inside the caller `EInventory` that belongs to |
||||
* the specified tag `tag`. |
||||
*/ |
||||
public function EItem GetTagItem(Text tag) { return none; } |
||||
|
||||
/** |
||||
* Returns array with all `EItem`s contained inside the caller `EInventory` |
||||
* that originated from the specified template `template`. |
||||
* |
||||
* @param template Template, that items we want to get originated from. |
||||
* @return Array with all `EItem`s contained inside the caller `EInventory` |
||||
* that originated from the specified template `template`. |
||||
*/ |
||||
public function array<EItem> GetTemplateItems(Text template) |
||||
{ |
||||
local array<EItem> emptyArray; |
||||
return emptyArray; |
||||
} |
||||
|
||||
/** |
||||
* Returns array with all `EItem`s contained inside the caller `EInventory` |
||||
* that originated from the specified template `template`. |
||||
* |
||||
* If several `EItem`s inside caller `EInventory` originated from |
||||
* that template, inventory system can pick one arbitrarily (can be based on |
||||
* simple convenience of implementation). Returned value does not have to |
||||
* be stable (the same after repeated calls). |
||||
* |
||||
* @param template Template, that item we want to get originated from. |
||||
* @return `EItem`s contained inside the caller `EInventory` that originated |
||||
* from the specified template `template`. |
||||
*/ |
||||
public function EItem GetTemplateItem(Text template) { return none; } |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
@ -0,0 +1,179 @@
|
||||
/** |
||||
* Abstract interface that represents some kind of item inside player's |
||||
* inventory. |
||||
* At most basic, abstract item has "template", "group" and "name": |
||||
* 1. "Template" refers to some sort of preset from which new instances of |
||||
* `EItem` can be created. "Template" might be implemented in any way, |
||||
* but the requirement is that "templates" can be referred to by |
||||
* case-insensitive, human-readable text value. In Killing Floor |
||||
* "templates" correspond to classes: for example, |
||||
* `KFMod.M79GrenadeLauncher` for M79 or `KFMod.M14EBRBattleRifle` |
||||
* for EBR. |
||||
* 2. "Tag" refers to the one of the groups inventory belongs to. |
||||
* For example all weapons would belong to group "weapons", while ammo |
||||
* or objective items can have their own group. But weapons can have |
||||
* several different tags further separating them, like "primary", |
||||
* "secondary" or "ultimate". |
||||
* 3. "Name" is simply a human-readable name of an item that is also fit |
||||
* to be output in UI. Like "M79 Grenade Launcher" instead of just |
||||
* "KFMod.M79GrenadeLauncher". |
||||
* We can also specify whether a certain item is allowed to be removed from |
||||
* inventory by player's own volition for any item. `IsRemovable()` method must |
||||
* return `true` if it can be. |
||||
* |
||||
* However, while `EItem` is meant to be abstract generalization for any |
||||
* kind of item, to help simplify access to common item data we have also |
||||
* added several additional groups of parameters: |
||||
* 1. Shop-related parameters. Price (accessed by `SetPrice()` and |
||||
* `GetPrice()`) and whether it is sellable (`IsSellable()`). Price |
||||
* should only be used if an item is sellable. |
||||
* 2. Weight. Accessed by `SetWeight()` / `GetWeight()`. |
||||
* All of these parameters can be ignored if they are not applicable to |
||||
* a certain type of item. |
||||
* Copyright 2021 Anton Tarasenko |
||||
*------------------------------------------------------------------------------ |
||||
* This file is part of Acedia. |
||||
* |
||||
* Acedia is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* Acedia is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
||||
*/ |
||||
class EItem extends AcediaObject |
||||
abstract; |
||||
|
||||
/** |
||||
* Returns arrays of tags for caller `EItem`. |
||||
* |
||||
* @return Tags for the caller `EItem`. Returned `Text` values are not allowed |
||||
* to be empty or `none`. There can be no duplicates (in case-insensitive |
||||
* sense). But returned array can be empty. |
||||
*/ |
||||
public function array<Text> GetTags() |
||||
{ |
||||
local array<Text> emptyArray; |
||||
return emptyArray; |
||||
} |
||||
|
||||
/** |
||||
* Returns template caller `EItem` was created from. |
||||
* |
||||
* @return Template caller `EItem` belongs to, even if it was modified to be |
||||
* something else entirely. `none` for dead `EItem`s. |
||||
*/ |
||||
public function Text GetTemplate() |
||||
{ |
||||
return none; |
||||
} |
||||
|
||||
/** |
||||
* Returns UI-usable name of the caller `EItem`. |
||||
* |
||||
* @return UI-usable name of the caller `EItem`. Allowed to be empty, |
||||
* not allowed to be `none`. `none` for dead `EItem`s. |
||||
*/ |
||||
public function Text GetName() |
||||
{ |
||||
return none; |
||||
} |
||||
|
||||
/** |
||||
* Checks whether this item can be removed as a result of player's action. |
||||
* |
||||
* We will not enforce items to be completely unremovable through the API, so |
||||
* this only marks an item as one unintended to be removed from inventory. |
||||
* Enforcing of this rule is up to the implementation. |
||||
* 9mm pistol is a good example for Killing Floor. |
||||
* |
||||
* Note that item being removable does not mean game must always (or ever) |
||||
* provide players with a way to remove that item, just that it can. |
||||
* |
||||
* @return `true` if caller `EItem` is removable by player and |
||||
* `false` otherwise. |
||||
*/ |
||||
public function bool IsRemovable() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Can caller `EItem` be sold? |
||||
* |
||||
* @return `true` if caller `EItem` can be sold and `false` otherwise. |
||||
*/ |
||||
public function bool IsSellable() |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Changes price of the caller `EItem`. |
||||
* Only applicable it item is sellable (`IsSellable() == true`). |
||||
* |
||||
* Price is allowed to have any integer value. |
||||
* |
||||
* Caller `EItem` is allowed to refuse this call and keep the old price. |
||||
* Setting new price, different from both old value and `newPrice` is |
||||
* forbidden. |
||||
* |
||||
* @return `true` if price was successfully changed and `false` otherwise. |
||||
*/ |
||||
public function bool SetPrice(int newPrice) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns current price of the caller `EItem`. |
||||
* Only applicable it item is sellable (`IsSellable() == true`). |
||||
* |
||||
* Price is allowed to have any integer value. |
||||
* |
||||
* @return Current price of the caller `EItem`. |
||||
*/ |
||||
public function int GetPrice() { return 0; } |
||||
|
||||
/** |
||||
* Returns "weight" of the caller `EItem`. |
||||
* A parameter widely used in Killing Floor. |
||||
* |
||||
* Weight is allowed to have any integer value. |
||||
* |
||||
* Caller `EItem` is allowed to refuse this call and keep the old weight. |
||||
* Setting new weight, different from both old value and `newWeight` is |
||||
* forbidden. |
||||
* |
||||
* @return `true` if weight was successfully changed and `false` otherwise. |
||||
*/ |
||||
public function bool SetWeight(int newWeight) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns current weight of the caller `EItem`. |
||||
* |
||||
* Weight is allowed to have any integer value. |
||||
* |
||||
* If concept of weight is not applicable, this method should return `0`. |
||||
* However inverse does not hold - returning `0` does not mean that weight |
||||
* is not applicable for the caller `EItem`. |
||||
* |
||||
* @return Current weight of the caller `EItem`. |
||||
*/ |
||||
public function int GetWeight() |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
@ -0,0 +1,67 @@
|
||||
/** |
||||
* Abstract interface that represents information about some kind of item. |
||||
* It refers to some sort of preset from which new instances of `EItem` |
||||
* can be created. "Template" might be implemented in any way, but |
||||
* the requirement is that "templates" can be referred to by case-insensitive, |
||||
* human-readable text value. In Killing Floor "templates" correspond to |
||||
* classes: for example, `KFMod.M79GrenadeLauncher` for M79 or |
||||
* `KFMod.M14EBRBattleRifle` for EBR. However Acedia adds its own parameters |
||||
* (such as tags) on top. |
||||
* Copyright 2021 Anton Tarasenko |
||||
*------------------------------------------------------------------------------ |
||||
* This file is part of Acedia. |
||||
* |
||||
* Acedia is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* Acedia is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
||||
*/ |
||||
class EItemTemplateInfo extends AcediaObject |
||||
abstract; |
||||
|
||||
/** |
||||
* Returns arrays of tags for caller `EItem`. |
||||
* |
||||
* @return Tags for the caller `EItem`. Returned `Text` values are not allowed |
||||
* to be empty or `none`. There can be no duplicates (in case-insensitive |
||||
* sense). But returned array can be empty. |
||||
*/ |
||||
public function array<Text> GetTags() |
||||
{ |
||||
local array<Text> emptyArray; |
||||
return emptyArray; |
||||
} |
||||
|
||||
/** |
||||
* Returns template caller `EItem` was created from. |
||||
* |
||||
* @return Template caller `EItem` belongs to, even if it was modified to be |
||||
* something else entirely. `none` for dead `EItem`s. |
||||
*/ |
||||
public function Text GetTemplateName() |
||||
{ |
||||
return none; |
||||
} |
||||
|
||||
/** |
||||
* Returns UI-usable name of the caller `EItem`. |
||||
* |
||||
* @return UI-usable name of the caller `EItem`. Allowed to be empty, |
||||
* not allowed to be `none`. `none` for dead `EItem`s. |
||||
*/ |
||||
public function Text GetName() |
||||
{ |
||||
return none; |
||||
} |
||||
|
||||
defaultproperties |
||||
{ |
||||
} |
Loading…
Reference in new issue