forked from zcaliptium/gdinv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GDInv_Inventory.gd
213 lines (163 loc) · 5.89 KB
/
GDInv_Inventory.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# Copyright (c) 2019-2020 ZCaliptium.
extends Object
class_name GDInv_Inventory
# Signals.
signal stack_added(slot);
signal stack_merged(slot, count);
signal stack_decreased(slot);
signal stack_removed(slot);
signal cleaned_up();
# Fields.
export var RestrictStackSize: bool = true;
export var MaxStacks: int = 0;
var STACKS: Array = [];
# Called when node enters tree.
func _ready() -> void:
init();
# Should be called for any finite inventory.
func init() -> void:
# warning-ignore:unused_variable
for i in range(0, MaxStacks):
STACKS.append(null);
# Removes all items from slots.
func clear() -> void:
STACKS.clear();
if (MaxStacks > 0):
init();
emit_signal("cleaned_up");
# Tries to add item by identifier. Returns true on success, otherwise false.
func add_item_by_id(item_id: String, count: int = 1) -> bool:
var item_def: GDInv_ItemDefinition = GDInv_ItemDB.get_item_by_id(item_id);
if (item_def == null):
return false;
return add_item(item_def, count);
# Tries to add item by item definition reference.
# Returns true on success, otherwise false.
func add_item(item_def: GDInv_ItemDefinition, count: int = 1) -> bool:
var new_stack = GDInv_ItemStack.new(item_def, count);
return add_stack(new_stack);
# Tries to put stack into inventory.
# Returns true on success, otherwise false.
func add_stack(stack: GDInv_ItemStack) -> bool:
var firstEmptySlot: int = -1;
# Iterate trough inventory.
for i in range(0, STACKS.size()):
var element: GDInv_ItemStack = STACKS[i];
# Remember first empty slot.
if ((firstEmptySlot == -1) && (element == null)):
firstEmptySlot = i;
# If found stack with equal item definition.
if (element != null && element.item == stack.item):
# Ignore stack size.
if (!RestrictStackSize || element.item.maxStackSize < 1):
element.stackSize += stack.stackSize;
emit_signal("stack_merged", i, stack.stackSize);
return true;
var maxStackSize: int = element.item.maxStackSize;
# Skip full stacks.
if (element.stackSize >= maxStackSize):
continue;
var neededToFill: int = maxStackSize - element.stackSize;
# If can be merged into one stack completelly.
if (neededToFill >= stack.stackSize):
element.stackSize += stack.stackSize;
emit_signal("stack_merged", i, stack.stackSize);
return true;
else:
# Fill that stack.
element.stackSize = maxStackSize;
emit_signal("stack_merged", i, neededToFill);
stack.stackSize -= neededToFill; # Change items at source stack.
# If we can't find stack with same items then we put stack into first empty slot.
if (firstEmptySlot != -1):
STACKS[firstEmptySlot] = stack;
emit_signal("stack_added", firstEmptySlot);
return true;
# If infinite inventory then we can expand it.
if (MaxStacks <= 0):
STACKS.append(stack);
emit_signal("stack_added", STACKS.size() - 1);
return true;
return false;
# Tries to remove item by identifier.
# Returns amount of removed items. If -1 then it means item_def is null!
func remove_item_by_id(item_id: String, count: int = 1) -> int:
var item_def: GDInv_ItemDefinition = GDInv_ItemDB.get_item_by_id(item_id);
if (item_def == null):
return -1;
return remove_item(item_def, count);
# Tries to remove item by item definition reference.
# Returns amount of removed items. If -1 then it means item_def is null!
func remove_item(item_def: GDInv_ItemDefinition, count: int = 1) -> int:
var removedItems: int = 0;
# Iterate trough inventory.
for i in range(0, STACKS.size()):
var element: GDInv_ItemStack = STACKS[i];
# Skip empty slots.
if (element == null):
continue;
# If same definition.
if (element.item == item_def):
# If enough items. Then just decrement stack.
if (element.stackSize > count):
removedItems += count;
element.stackSize -= count;
emit_signal("stack_decreased", i);
return removedItems;
# If exactly needed item count. Then just remove stack.
elif (element.stackSize == count):
removedItems += count;
STACKS[i] = null;
emit_signal("stack_removed", i);
return removedItems;
# If not enough items in stack. And continue cycle.
removedItems += element.stackSize;
count -= element.stackSize;
STACKS[i] = null;
emit_signal("stack_removed", i);
return removedItems;
# Returns slot number with item that has specified identifier. Otherwise -1.
func find_item_by_id(item_id: String, start: int = 0) -> int:
var item_def: GDInv_ItemDefinition = GDInv_ItemDB.get_item_by_id(item_id);
if (item_def == null):
return -1;
return find_item(item_def, start);
# Returns slot number with item that has specified ItemDefinition instance. Otherwise -1.
func find_item(item_def:GDInv_ItemDefinition, start: int = 0) -> int:
var numStacks = STACKS.size();
if (start >= numStacks):
return -1;
# Iterate trough inventory.
for i in range(start, numStacks):
var element: GDInv_ItemStack = STACKS[i];
if (element != null && element.item == item_def):
return i;
return -1;
# Returns stack at slot. Returns null if stack isn't present or slot number is invalid.
func at_slot(slot_id: int) -> GDInv_ItemStack:
if (slot_id < 0 || slot_id >= STACKS.size()):
return null;
var stack: GDInv_ItemStack = STACKS[slot_id];
return stack;
# Returns reference to stack in slot. Removes stack from slot simultaneously.
func take_from_slot(slot_id: int) -> GDInv_ItemStack:
if (slot_id < 0 || slot_id >= STACKS.size()):
return null;
var stack: GDInv_ItemStack = STACKS[slot_id];
STACKS[slot_id] = null; # Remove from the slot.
emit_signal("stack_removed", slot_id);
return stack;
# Decrements item count at slot
func dec_in_slot(slot_id: int) -> void:
if (slot_id < 0 || slot_id >= STACKS.size()):
return;
var stack: GDInv_ItemStack = STACKS[slot_id];
if (stack == null):
return;
stack.stackSize -= 1;
if (stack.stackSize <= 0):
if (MaxStacks > 0):
STACKS[slot_id] = null;
else:
STACKS.erase(slot_id);
emit_signal("stack_removed", slot_id);