]> git.lizzy.rs Git - dungeon_game.git/blob - plugins/inventory/inventory.c
66f663ea07c154b3ba7cb43c3fcc5b15c2f046c0
[dungeon_game.git] / plugins / inventory / inventory.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "../inventory/inventory.h"
4
5 static struct color gray;
6 static struct color darkgray;
7
8 static bool use_item(struct itemstack *stack)
9 {
10         (void) stack;
11         return true;
12 }
13
14 struct inventory player_inventory = {NULL};
15
16 static int selected_index = 0;
17
18 void inventory_add(struct inventory *self, struct itemstack stack)
19 {
20         struct list **ptr = &self->stacks;
21
22         if (stack.item->stackable) {
23                 for (; *ptr != NULL; ptr = &(*ptr)->next) {
24                         struct itemstack *other = (*ptr)->element;
25                         if (other->item == stack.item) {
26                                 other->count += stack.count;
27                                 return;
28                         }
29                 }
30         }
31
32         struct itemstack *buf = make_buffer(&stack, sizeof(struct itemstack));
33         *ptr = add_element(*ptr, buf);
34
35         if (buf->item->on_create)
36                 buf->item->on_create(buf);
37 }
38
39 /*
40
41 bool inventory_remove(struct inventory *self, struct itemstack *stack)
42 {
43         stack.count = -stack.count;
44
45         for (struct list **ptr = &self->stacks; *ptr != NULL; ) {
46                 struct itemstack *other = (*ptr)->element;
47
48                 if (other->item == stack.item) {
49                         stack.count += other->count;
50
51                         if (stack.count > 0) {
52                                 other->count = stack.count;
53                                 return true;
54                         } else {
55                                 struct list *next = ptr->next;
56
57                                 other->count = 0;
58
59                                 if (other->item->on_destroy)
60                                         other->item->on_destroy(other);
61
62                                 free(other);
63                                 free(*ptr);
64
65                                 *ptr = next;
66                                 continue;
67                         }
68                 }
69
70                 ptr = &(*ptr)->next;
71         }
72
73         return false;
74 }
75
76 */
77
78 static void decrease_item_count(struct list **ptr)
79 {
80         struct itemstack *stack = (*ptr)->element;
81
82         stack->count--;
83
84         if (stack->count == 0) {
85                 struct list *next = (*ptr)->next;
86
87                 if (stack->item->on_destroy)
88                         stack->item->on_destroy(stack);
89
90                 if (stack->meta)
91                         free(stack->meta);
92
93                 free(stack);
94                 free(*ptr);
95
96                 *ptr = next;
97         }
98 }
99
100 static struct list **find_item(struct inventory *self, struct item *item)
101 {
102         for (struct list **ptr = &self->stacks; *ptr != NULL; ptr = &(*ptr)->next) {
103                 struct itemstack *stack = (*ptr)->element;
104
105                 if (stack->item == item)
106                         return ptr;
107         }
108
109         return NULL;
110 }
111
112 bool inventory_remove(struct inventory *self, struct item *item)
113 {
114         struct list **ptr = find_item(self, item);
115
116         if (ptr) {
117                 decrease_item_count(ptr);
118                 return true;
119         }
120
121         return false;
122 }
123
124 struct itemstack *inventory_find(struct inventory *self, struct item *item)
125 {
126         struct list **ptr = find_item(self, item);
127         return ptr ? (*ptr)->element : NULL;
128 }
129
130 static void handle_enter()
131 {
132         int i = 0;
133
134         for (struct list **ptr = &player_inventory.stacks; *ptr != NULL; ptr = &(*ptr)->next, i++) {
135                 if (i == selected_index) {
136                         struct itemstack *stack = (*ptr)->element;
137
138                         if (stack->item->on_use && stack->item->on_use(stack))
139                                 decrease_item_count(ptr);
140
141                         return;
142                 }
143         }
144 }
145
146 static void handle_arrow()
147 {
148         char c = fgetc(stdin);
149         if (c == '[') {
150                 char dir = fgetc(stdin);
151
152                 int count = 0;
153
154                 for (struct list *ptr = player_inventory.stacks; ptr != NULL; ptr = ptr->next)
155                         count++;
156
157                 if (count == 0)
158                         return;
159
160                 switch (dir) {
161                         case 'A':
162                                 selected_index--;
163
164                                 if (selected_index < 0)
165                                         selected_index = count - 1;
166                                 break;
167                         case 'B':
168                                 selected_index++;
169
170                                 if (selected_index >= count)
171                                         selected_index = 0;
172
173                                 break;
174                 }
175         } else {
176                 ungetc(c, stdin);
177         }
178 }
179
180 static void render_inventory(struct winsize ws)
181 {
182         printf("\e[3;0H");
183
184         printf(" \e[1mInventory\e[21m\n");
185
186         set_color(gray, false);
187
188         int i = 0;
189         for (struct list *ptr = player_inventory.stacks; ptr != NULL; ptr = ptr->next, i++) {
190                 struct itemstack *stack = ptr->element;
191
192                 if (i == selected_index) {
193                         printf(" \e[39m→ ");
194                         set_color(gray, false);
195                 } else {
196                         printf("   ");
197                 }
198
199                 printf("%s", stack->item->name);
200
201                 if (stack->count > 1) {
202                         set_color(darkgray, false);
203                         printf(" (x%u)", stack->count);
204                         set_color(gray, false);
205                 }
206
207                 printf("\n");
208         }
209 }
210
211 __attribute__ ((constructor)) static void init()
212 {
213         gray = get_color("#9E9E9E");
214         darkgray = get_color("#555555");
215
216         register_render_component(&render_inventory);
217
218         register_input_handler('\033', (struct input_handler) {
219                 .run_if_dead = false,
220                 .callback = &handle_arrow,
221         });
222
223         register_input_handler('\n', (struct input_handler) {
224                 .run_if_dead = false,
225                 .callback = &handle_enter,
226         });
227 }