|
@@ -1,22 +1,109 @@
|
1
|
1
|
#include <pokeagb/pokeagb.h>
|
2
|
2
|
|
3
|
|
-enum PalStoreType{
|
4
|
|
- UNUSED,
|
5
|
|
- NPC,
|
6
|
|
- REFLECTION,
|
7
|
|
- OTHER
|
8
|
|
-};
|
|
3
|
+#define MAX_PAL_STORE 16
|
9
|
4
|
|
10
|
|
-struct PalStoreEntry{
|
11
|
|
- enum PalStoreType type;
|
|
5
|
+struct PalStoreEntry {
|
12
|
6
|
u8 reference_count;
|
13
|
|
- u16 tag;
|
|
7
|
+ u16 tag;
|
14
|
8
|
};
|
15
|
9
|
|
16
|
10
|
extern struct PalStoreEntry stored_palettes[16];
|
17
|
11
|
|
18
|
|
-u8 dynamic_npc_load_palette(u16 tag)
|
19
|
|
-{
|
|
12
|
+extern struct NpcType *npc_get_type(u16 id);
|
|
13
|
+
|
|
14
|
+extern void dprintf(const char *str, ...);
|
|
15
|
+
|
|
16
|
+s8 npc_dynamic_find_palette(u16 tag) {
|
|
17
|
+ for (s8 i = 0; i < MAX_PAL_STORE; ++i) {
|
|
18
|
+ if (stored_palettes[i].reference_count > 0 && stored_palettes[i].tag == tag)
|
|
19
|
+ return i;
|
|
20
|
+ }
|
|
21
|
+ return -1;
|
|
22
|
+}
|
|
23
|
+
|
|
24
|
+s8 npc_dynamic_allocate_palette(u16 tag) {
|
|
25
|
+ for (s8 i = 0; i < MAX_PAL_STORE; ++i) {
|
|
26
|
+ if (stored_palettes[i].reference_count == 0) {
|
|
27
|
+ stored_palettes[i].tag = tag;
|
|
28
|
+ stored_palettes[i].reference_count++;
|
|
29
|
+ return i;
|
|
30
|
+ }
|
|
31
|
+ }
|
|
32
|
+ return -1;
|
|
33
|
+}
|
|
34
|
+
|
|
35
|
+u8 npc_dynamic_load_palette(u16 tag) {
|
|
36
|
+ s8 store_entry = npc_dynamic_find_palette(tag);
|
|
37
|
+ if (store_entry != -1) {
|
|
38
|
+ stored_palettes[store_entry].reference_count++;
|
|
39
|
+ return store_entry;
|
|
40
|
+ }
|
|
41
|
+ store_entry = npc_dynamic_allocate_palette(tag);
|
|
42
|
+ if (store_entry == -1) {
|
|
43
|
+ /* we do not have allocation space left */
|
|
44
|
+ dprintf("ATTENTION: TRIED TO ALLOCATE DYNOVER PALETTE WITHOUT SPACE LEFT, INCREASING ZERO REFERENCE\n");
|
|
45
|
+ stored_palettes[0].reference_count++;
|
|
46
|
+ return 0;
|
|
47
|
+ }
|
|
48
|
+
|
|
49
|
+ pal_patch_for_npc(tag, (u8)store_entry);
|
|
50
|
+
|
|
51
|
+ return (u8)store_entry;
|
|
52
|
+}
|
|
53
|
+
|
|
54
|
+void npc_dynamic_reset() {
|
|
55
|
+ for (u8 i = 0; i < MAX_PAL_STORE; ++i) {
|
|
56
|
+ stored_palettes[i].reference_count = 0;
|
|
57
|
+ stored_palettes[i].tag = 0;
|
|
58
|
+ }
|
|
59
|
+}
|
20
|
60
|
|
|
61
|
+void npc_dynamic_remove_entry(u8 id) {
|
|
62
|
+ if (stored_palettes[id].reference_count > 0) {
|
|
63
|
+ stored_palettes[id].reference_count--;
|
|
64
|
+ dprintf("npc_dynamic: removed entry #%d\n", id);
|
|
65
|
+ if (stored_palettes[id].reference_count == 0)
|
|
66
|
+ stored_palettes[id].tag = 0;
|
|
67
|
+ }
|
21
|
68
|
}
|
22
|
69
|
|
|
70
|
+u8 npc_spawn_with_provided_template(struct RomNpc *npc, struct Template *template, u8 map, u8 bank, s16 x, s16 y) {
|
|
71
|
+ u8 state = rom_npc_to_npc_state(npc, map, bank);
|
|
72
|
+ if (state >= 16)
|
|
73
|
+ return 16;
|
|
74
|
+
|
|
75
|
+ struct NpcState *created_state = &npc_states[state];
|
|
76
|
+ struct NpcType *type = npc_get_type(created_state->type_id | (npc->field3 << 8));
|
|
77
|
+ s8 pal_slot = npc_dynamic_load_palette(type->pal_num);
|
|
78
|
+
|
|
79
|
+ if (created_state->running_behavior == 76)
|
|
80
|
+ created_state->field1 |= 0x20;
|
|
81
|
+ template->pal_tag = 0xFFFF;
|
|
82
|
+ u8 obj_id = template_instanciate_forward_search(template, 0, 0, 0);
|
|
83
|
+ if (obj_id == 64) {
|
|
84
|
+ created_state->bitfield &= 0xFE;
|
|
85
|
+ return 16;
|
|
86
|
+ }
|
|
87
|
+
|
|
88
|
+ struct Object *npc_object = &objects[obj_id];
|
|
89
|
+ npc_fix_position(x + created_state->to.x, y + created_state->to.y, &npc_object->pos1.x, &npc_object->pos1.y);
|
|
90
|
+ npc_object->shift.x = -(type->pos_neg_center.x / 2);
|
|
91
|
+ npc_object->shift.y = -(type->pos_neg_center.y / 2);
|
|
92
|
+ npc_object->pos1.x += 8;
|
|
93
|
+ npc_object->pos1.y += (s8)npc_object->shift.y + 16;
|
|
94
|
+
|
|
95
|
+ /* Set our allocated index */
|
|
96
|
+ npc_object->final_oam.palette_num = pal_slot;
|
|
97
|
+ npc_object->bitfield2 |= 2;
|
|
98
|
+ npc_object->priv[0] = state;
|
|
99
|
+ created_state->oam_id = obj_id;
|
|
100
|
+
|
|
101
|
+ u8 unknown = (created_state->field1 & 0xEF) | (16 * (type->pal_slot_unk << 25 >> 31));
|
|
102
|
+ created_state->field1 = unknown;
|
|
103
|
+ if (!(unknown & 0x10)) {
|
|
104
|
+ obj_anim_image_start(npc_object, npc_direction_to_obj_anim_image_number(created_state->direction));
|
|
105
|
+ }
|
|
106
|
+ npc_y_height_related(created_state->height >> 4, npc_object, 1);
|
|
107
|
+ npc_obj_offscreen_culling_and_flag_update(created_state, npc_object);
|
|
108
|
+ return state;
|
|
109
|
+}
|