|
@@ -0,0 +1,162 @@
|
|
1
|
+#include <pokeagb/pokeagb.h>
|
|
2
|
+#include <agb_debug.h>
|
|
3
|
+#include "trainer_rival_encounters.h"
|
|
4
|
+
|
|
5
|
+void battle_intro_launch(u8 environment) {
|
|
6
|
+ TaskCallback introTask;
|
|
7
|
+ if (battle_type_flags & BATTLE_FLAG_LINK) {
|
|
8
|
+ introTask = (TaskCallback)(0x080BCC4C | 1);
|
|
9
|
+ } else if (battle_type_flags & 0x1000 && build_edition_identifier != 2) {
|
|
10
|
+ introTask = (TaskCallback)(0x080BC6C8 | 1);
|
|
11
|
+ } else {
|
|
12
|
+ introTask = task00_battle_intro_by_env[environment];
|
|
13
|
+ }
|
|
14
|
+ struct Task *livingTask = &tasks[task_add(introTask, 0)];
|
|
15
|
+ for (u8 i = 0; i <= 6; ++i)
|
|
16
|
+ livingTask->priv[i] = 0;
|
|
17
|
+ livingTask->priv[1] = environment;
|
|
18
|
+}
|
|
19
|
+
|
|
20
|
+union TrainerPokemonPtr battle_trainer_get_rival(u8 chosenStarterValue, u8 encounterNumber, enum TrainerPartyFlag flag) {
|
|
21
|
+ u8 partyCount = rival_encounters[encounterNumber].partyCount;
|
|
22
|
+ u8 structureSize = 0;
|
|
23
|
+ switch(flag)
|
|
24
|
+ {
|
|
25
|
+ case TRAINER_PARTY_NONE:
|
|
26
|
+ structureSize = sizeof(struct TrainerPokemonBase);
|
|
27
|
+ break;
|
|
28
|
+ case TRAINER_PARTY_HELD_ITEM:
|
|
29
|
+ structureSize = sizeof(struct TrainerPokemonItem);
|
|
30
|
+ break;
|
|
31
|
+ case TRAINER_PARTY_MOVESET:
|
|
32
|
+ structureSize = sizeof(struct TrainerPokemonMoves);
|
|
33
|
+ break;
|
|
34
|
+ case TRAINER_PARTY_HELD_ITEM_MOVESET:
|
|
35
|
+ structureSize = sizeof(struct TrainerPokemonItemMoves);
|
|
36
|
+ break;
|
|
37
|
+ default:
|
|
38
|
+ structureSize = sizeof(struct TrainerPokemonBase);
|
|
39
|
+ break;
|
|
40
|
+ }
|
|
41
|
+
|
|
42
|
+ return (union TrainerPokemonPtr)(rival_encounters[encounterNumber].partyArray.undefinedStructure + (chosenStarterValue * partyCount * structureSize));
|
|
43
|
+}
|
|
44
|
+
|
|
45
|
+#define VAR_STARTER 0x5052
|
|
46
|
+
|
|
47
|
+union TrainerPokemonPtr battle_trainer_get_rival_or_null(u8 tid) {
|
|
48
|
+ for(u16 i = 0; i < RIVAL_ENCOUNTER_COUNT; ++i) {
|
|
49
|
+ if(rival_encounters[i].trainerId == tid) {
|
|
50
|
+ return battle_trainer_get_rival(var_load(VAR_STARTER), i, trainer_data[tid].flags);
|
|
51
|
+ }
|
|
52
|
+ }
|
|
53
|
+ union TrainerPokemonPtr nullPokemon = {.undefinedStructure = NULL};
|
|
54
|
+ return nullPokemon;
|
|
55
|
+}
|
|
56
|
+
|
|
57
|
+u8 battle_trainer_build_party(struct Pokemon *party, u16 tid) {
|
|
58
|
+ if(tid == 0x400)
|
|
59
|
+ return 0;
|
|
60
|
+ //ignore some type of battles like old man or trainer tower where the party is determined otherwise
|
|
61
|
+ dprintf("battle_type_flags: %x, tid: %d\n", battle_type_flags, tid);
|
|
62
|
+ if ((battle_type_flags & 0x80908) == 8) {
|
|
63
|
+ party_opponent_purge();
|
|
64
|
+ for(u8 i = 0; i < trainer_data[tid].party_size; ++i) {
|
|
65
|
+ u32 personalityValue;
|
|
66
|
+ if(trainer_data[tid].is_double)
|
|
67
|
+ personalityValue = 0x80;
|
|
68
|
+ else if (trainer_data[tid].gender & 0x80)
|
|
69
|
+ personalityValue = 0x78;
|
|
70
|
+ else
|
|
71
|
+ personalityValue = 0x88;
|
|
72
|
+ u32 nameHash = 0;
|
|
73
|
+ for(u8 j = 0; trainer_data[tid].name[j] != 0xFF; ++j){
|
|
74
|
+ nameHash += trainer_data[tid].name[j];
|
|
75
|
+ }
|
|
76
|
+ //has custom items etc
|
|
77
|
+ switch(trainer_data[tid].flags)
|
|
78
|
+ {
|
|
79
|
+ case TRAINER_PARTY_NONE:
|
|
80
|
+ {
|
|
81
|
+ //nothing
|
|
82
|
+ const struct TrainerPokemonBase *pokeData = battle_trainer_get_rival_or_null(tid).noItemDefaultMoves;
|
|
83
|
+ if(pokeData == NULL)
|
|
84
|
+ pokeData = trainer_data[tid].party.noItemDefaultMoves;
|
|
85
|
+ dprintf("making pokemon with species: %d, struct: 0x%x\n", pokeData[i].species, pokeData);
|
|
86
|
+ for(u8 j = 0; pokemon_names[pokeData[i].species][j] != 0xFF; ++j) {
|
|
87
|
+ nameHash += pokemon_names[pokeData[i].species][j];
|
|
88
|
+ }
|
|
89
|
+
|
|
90
|
+ personalityValue += nameHash << 8;
|
|
91
|
+ u8 iv = pokeData[i].iv * 31 / 255;
|
|
92
|
+
|
|
93
|
+ //no idea about the last 2 parameters, just do what the game does I guess
|
|
94
|
+ pokemon_make_full(&party[i], pokeData[i].species, pokeData[i].level, iv, true, personalityValue, 2, 0);
|
|
95
|
+ break;
|
|
96
|
+ }
|
|
97
|
+ case TRAINER_PARTY_MOVESET:
|
|
98
|
+ {
|
|
99
|
+ const struct TrainerPokemonMoves *pokeData = battle_trainer_get_rival_or_null(tid).noItemCustomMoves;
|
|
100
|
+ if(pokeData == NULL)
|
|
101
|
+ pokeData = trainer_data[tid].party.noItemCustomMoves;
|
|
102
|
+
|
|
103
|
+ dprintf("making pokemon with species: %d\n", pokeData[i].species);
|
|
104
|
+ //custom moveset
|
|
105
|
+ for(u8 j = 0; pokemon_names[pokeData[i].species][j] != 0xFF; ++j)
|
|
106
|
+ nameHash += pokemon_names[pokeData[i].species][j];
|
|
107
|
+ personalityValue += nameHash << 8;
|
|
108
|
+ u8 iv = pokeData[i].iv * 31 / 255;
|
|
109
|
+ pokemon_make_full(&party[i], pokeData[i].species, pokeData[i].level, iv, true, personalityValue, 2, 0);
|
|
110
|
+ for(u8 j = 0; j < 4; ++j) {
|
|
111
|
+ pokemon_setattr(&party[i], REQUEST_MOVE1 + j, (void*)&pokeData[i].moves[j]);
|
|
112
|
+ pokemon_setattr(&party[i], REQUEST_PP1 + j, (void*)&pokemon_moves[pokeData[i].moves[j]].pp);
|
|
113
|
+ }
|
|
114
|
+ break;
|
|
115
|
+ }
|
|
116
|
+ case TRAINER_PARTY_HELD_ITEM:
|
|
117
|
+ {
|
|
118
|
+ //custom item
|
|
119
|
+
|
|
120
|
+ const struct TrainerPokemonItem *pokeData = battle_trainer_get_rival_or_null(tid).itemDefaultMoves;
|
|
121
|
+ if(pokeData == NULL)
|
|
122
|
+ pokeData = trainer_data[tid].party.itemDefaultMoves;
|
|
123
|
+
|
|
124
|
+ dprintf("making pokemon with species: %d\n", pokeData[i].species);
|
|
125
|
+ for(u8 j = 0; pokemon_names[pokeData[i].species][j] != 0xFF; ++j)
|
|
126
|
+ nameHash += pokemon_names[pokeData[i].species][j];
|
|
127
|
+ personalityValue += nameHash << 8;
|
|
128
|
+ u8 iv = pokeData[i].iv * 31 / 255;
|
|
129
|
+ pokemon_make_full(&party[i], pokeData[i].species, pokeData[i].level, iv, true, personalityValue, 2, 0);
|
|
130
|
+
|
|
131
|
+ pokemon_setattr(&party[i], REQUEST_HELD_ITEM, (void*)&pokeData[i].Item);
|
|
132
|
+ break;
|
|
133
|
+ }
|
|
134
|
+ case TRAINER_PARTY_HELD_ITEM | TRAINER_PARTY_MOVESET:
|
|
135
|
+ {
|
|
136
|
+ //custom all the things
|
|
137
|
+ const struct TrainerPokemonItemMoves *pokeData = battle_trainer_get_rival_or_null(tid).customItemCustomMoves;
|
|
138
|
+ if(pokeData == NULL)
|
|
139
|
+ pokeData = trainer_data[tid].party.customItemCustomMoves;
|
|
140
|
+
|
|
141
|
+ dprintf("making pokemon with species: %d\n", pokeData[i].species);
|
|
142
|
+ for(u8 j = 0; pokemon_names[pokeData[i].species][j] != 0xFF; ++j)
|
|
143
|
+ nameHash += pokemon_names[pokeData[i].species][j];
|
|
144
|
+ personalityValue += nameHash << 8;
|
|
145
|
+ u8 iv = pokeData[i].iv * 31 / 255;
|
|
146
|
+ pokemon_make_full(&party[i], pokeData[i].species, pokeData[i].level, iv, true, personalityValue, 2, 0);
|
|
147
|
+
|
|
148
|
+ pokemon_setattr(&party[i], REQUEST_HELD_ITEM, (void*)&pokeData[i].Item);
|
|
149
|
+ for(u8 j = 0; j < 4; ++j) {
|
|
150
|
+ pokemon_setattr(&party[i], REQUEST_MOVE1 + j, (void*)&pokeData[i].moves[j]);
|
|
151
|
+ pokemon_setattr(&party[i], REQUEST_PP1 + j, (void*)&pokemon_moves[pokeData[i].moves[j]].pp);
|
|
152
|
+ }
|
|
153
|
+ break;
|
|
154
|
+ }
|
|
155
|
+
|
|
156
|
+ }
|
|
157
|
+ }
|
|
158
|
+ battle_type_flags |= trainer_data[tid].is_double;
|
|
159
|
+ }
|
|
160
|
+ (void) party;
|
|
161
|
+ return trainer_data[tid].party_size;
|
|
162
|
+}
|