dragonflysots преди 5 години
родител
ревизия
17f74d4ff8

+ 2
- 0
data/moves/move_data.s Целия файл

@@ -6,6 +6,8 @@
6 6
 
7 7
 .global move_table
8 8
 move_table:
9
+.global pokemon_moves
10
+pokemon_moves:
9 11
 
10 12
 @Move			DATA		.BYTE		EFFECT		DMG		TYPE		ACCUR		PP		EF_ACC		TARGET		PRIO		FLAGS		AGR_1		SPLIT		AGR_2
11 13
 /*Nichts*/		move_data_0:	.byte		0,		0,		0,		0,		0,		0,		0,		0,		0,		0,		0,		0

+ 3
- 2
data/trainer/trainer_pkmn_data.s Целия файл

@@ -3,8 +3,8 @@
3 3
 .align 2
4 4
 .text
5 5
 .thumb
6
-.global trainer_pkmn_data
7
-trainer_pkmn_data:
6
+.global trainer_data
7
+trainer_data:
8 8
 
9 9
 .byte 0x0
10 10
 .byte 0x0
@@ -21,6 +21,7 @@ trainer_pkmn_data:
21 21
 .hword 0x0, 0x0
22 22
 .byte 0x0
23 23
 .byte 0x0, 0x0, 0x0
24
+.word 0x00000000 @@this is actually important, because otherwise the structure offset will be off
24 25
 
25 26
 .byte MOVE_NEIN_ITEM_NEIN
26 27
 .byte TRAINERCLASS_PKMN_TRAINER

+ 1
- 1
g3headers

@@ -1 +1 @@
1
-Subproject commit 4f2398d73aba67dfbc4dd396c2b8f3a376c64ea9
1
+Subproject commit 3e36531d290bd97e7b1208526e54c8acdfe376d3

+ 5
- 0
patches/overworlds/trainer.asm Целия файл

@@ -11,4 +11,9 @@ bx r2
11 11
 .org 0x080BC3A0
12 12
 ldr r1, =battle_intro_launch+1
13 13
 bx r1
14
+.pool
15
+
16
+.org 0x080112E0
17
+ldr r2, =battle_trainer_build_party+1
18
+bx r2
14 19
 .pool

+ 22
- 22
patches/trainer_sprites/trainer_data.asm Целия файл

@@ -1,67 +1,67 @@
1 1
 //Point to trainer data, which is 4 bytes prior to the first name
2 2
 
3 3
 .org 0x0800FC00
4
-.word trainer_pkmn_data -4
4
+.word trainer_data
5 5
 
6 6
 .org 0x0800FC80
7
-.word trainer_pkmn_data -4
7
+.word trainer_data
8 8
 
9 9
 .org 0x0801133C
10
-.word trainer_pkmn_data -4
10
+.word trainer_data
11 11
 
12 12
 .org 0x080113BC
13
-.word trainer_pkmn_data -4
13
+.word trainer_data
14 14
 
15 15
 .org 0x080116C4
16
-.word trainer_pkmn_data -4
16
+.word trainer_data
17 17
 
18 18
 .org 0x08015728
19
-.word trainer_pkmn_data -4
19
+.word trainer_data
20 20
 
21 21
 .org 0x08025920
22
-.word trainer_pkmn_data -4
22
+.word trainer_data
23 23
 
24 24
 .org 0x080259DC
25
-.word trainer_pkmn_data -4
25
+.word trainer_data
26 26
 
27 27
 .org 0x08037E6C
28
-.word trainer_pkmn_data -4
28
+.word trainer_data
29 29
 
30 30
 .org 0x08038040
31
-.word trainer_pkmn_data -4
31
+.word trainer_data
32 32
 
33 33
 .org 0x08043694
34
-.word trainer_pkmn_data -4
34
+.word trainer_data
35 35
 
36 36
 .org 0x08043884
37
-.word trainer_pkmn_data -4
37
+.word trainer_data
38 38
 
39 39
 .org 0x08044028
40
-.word trainer_pkmn_data -4
40
+.word trainer_data
41 41
 
42 42
 .org 0x0807FE88
43
-.word trainer_pkmn_data -4
43
+.word trainer_data
44 44
 
45 45
 .org 0x0807FFB8
46
-.word trainer_pkmn_data -4
46
+.word trainer_data
47 47
 
48 48
 .org 0x080C6F40
49
-.word trainer_pkmn_data -4
49
+.word trainer_data
50 50
 
51 51
 .org 0x080D809C
52
-.word trainer_pkmn_data -4
52
+.word trainer_data
53 53
 
54 54
 .org 0x080D8158
55
-.word trainer_pkmn_data -4
55
+.word trainer_data
56 56
 
57 57
 .org 0x08113810
58
-.word trainer_pkmn_data -4
58
+.word trainer_data
59 59
 
60 60
 .org 0x08115230
61
-.word trainer_pkmn_data -4
61
+.word trainer_data
62 62
 
63 63
 .org 0x0812C048
64
-.word trainer_pkmn_data -4
64
+.word trainer_data
65 65
 
66 66
 .org 0x080D80A0
67 67
 .word trainerclasses
@@ -74,4 +74,4 @@
74 74
 
75 75
 //Point to new trainer item data
76 76
 .org 0x080C6D9C
77
-.word trainer_pkmn_data +12
77
+.word trainer_data +12

+ 0
- 16
src/overworld/trainerbattle_init.c Целия файл

@@ -1,16 +0,0 @@
1
-#include <pokeagb/pokeagb.h>
2
-
3
-void battle_intro_launch(u8 environment) {
4
-    TaskCallback introTask;
5
-    if (battle_type_flags & BATTLE_FLAG_LINK) {
6
-        introTask = (TaskCallback)(0x080BCC4C | 1);
7
-    } else if (battle_type_flags & 0x1000 && build_edition_identifier != 2) {
8
-        introTask = (TaskCallback)(0x080BC6C8 | 1);
9
-    } else {
10
-        introTask = task00_battle_intro_by_env[environment];
11
-    }
12
-    struct Task *livingTask = &tasks[task_add(introTask, 0)];
13
-    for (u8 i = 0; i <= 6; ++i)
14
-        livingTask->priv[i] = 0;
15
-    livingTask->priv[1] = environment;
16
-}

src/specials/trainer_battle.c → src/trainer/trainer_battle.c Целия файл


+ 170
- 0
src/trainer/trainer_rival_encounters.c Целия файл

@@ -0,0 +1,170 @@
1
+#include <pokeagb/pokeagb.h>
2
+#include <constants/pkmns.h>
3
+#include "trainer_rival_encounters.h"
4
+
5
+
6
+const struct TrainerPokemonBase rival_first_encounter[21][1] = {
7
+    //Bisasam
8
+    {
9
+        {
10
+            .species = PKMN_GLUMANDA,
11
+            .level = 5
12
+        },
13
+    },
14
+
15
+    //Glumanda
16
+    {
17
+        {
18
+            .species = PKMN_SCHIGGY,
19
+            .level = 5
20
+        },
21
+    },
22
+    //Schiggy
23
+    {
24
+        {
25
+            .species = PKMN_BISASAM,
26
+            .level = 5
27
+        },
28
+    },
29
+    //Endivie
30
+    {
31
+        {
32
+            .species = PKMN_FEURIGEL,
33
+            .level = 5
34
+        },
35
+    },
36
+
37
+    //Feurigel
38
+    {
39
+        {
40
+            .species = PKMN_KARNIMANI,
41
+            .level = 5
42
+        },
43
+    },
44
+    //Karnimani
45
+    {
46
+        {
47
+            .species = PKMN_ENDIVIE,
48
+            .level = 5
49
+        },
50
+    },
51
+    //Geckarbor
52
+    {
53
+        {
54
+            .species = PKMN_FLEMMLI,
55
+            .level = 5
56
+        },
57
+    },
58
+
59
+    //Flemmli
60
+    {
61
+        {
62
+            .species = PKMN_HYDROPI,
63
+            .level = 5
64
+        },
65
+    },
66
+    //Hydropi
67
+    {
68
+        {
69
+            .species = PKMN_GECKARBOR,
70
+            .level = 5
71
+        },
72
+    },
73
+    //Chelast
74
+    {
75
+        {
76
+            .species = PKMN_PANFLAM,
77
+            .level = 5
78
+        },
79
+    },
80
+
81
+    //Panflam
82
+    {
83
+        {
84
+            .species = PKMN_PLINFA,
85
+            .level = 5
86
+        },
87
+    },
88
+    //Plinfa
89
+    {
90
+        {
91
+            .species = PKMN_CHELAST,
92
+            .level = 5
93
+        },
94
+    },
95
+    //Serpifeu
96
+    {
97
+        {
98
+            .species = PKMN_FLOINK,
99
+            .level = 5
100
+        },
101
+    },
102
+
103
+    //Floink
104
+    {
105
+        {
106
+            .species = PKMN_OTTARO,
107
+            .level = 5
108
+        },
109
+    },
110
+    //Ottaro
111
+    {
112
+        {
113
+            .species = PKMN_SERPIFEU,
114
+            .level = 5
115
+        },
116
+    },
117
+    //Igamaro
118
+    {
119
+        {
120
+            .species = PKMN_FYNX,
121
+            .level = 5
122
+        },
123
+    },
124
+
125
+    //Fynx
126
+    {
127
+        {
128
+            .species = PKMN_FROXY,
129
+            .level = 5
130
+        },
131
+    },
132
+    //Froxy
133
+    {
134
+        {
135
+            .species = PKMN_IGAMARO,
136
+            .level = 5
137
+        },
138
+    },
139
+    //Bauz
140
+    {
141
+        {
142
+            .species = PKMN_FLAMIAU,
143
+            .level = 5
144
+        },
145
+    },
146
+
147
+    //Flamiau
148
+    {
149
+        {
150
+            .species = PKMN_ROBBALL,
151
+            .level = 5
152
+        },
153
+    },
154
+    //Robball
155
+    {
156
+        {
157
+            .species = PKMN_BAUZ,
158
+            .level = 5
159
+        },
160
+    },
161
+};
162
+
163
+const struct RivalEncounter rival_encounters[RIVAL_ENCOUNTER_COUNT] = {
164
+    {.partyCount = 1, .partyArray = {&rival_first_encounter[0][0]}, .trainerId = 1}, //male easy
165
+    {.partyCount = 1, .partyArray = {&rival_first_encounter[0][0]}, .trainerId = 2}, //male medium
166
+    {.partyCount = 1, .partyArray = {&rival_first_encounter[0][0]}, .trainerId = 3}, //male hard
167
+    {.partyCount = 1, .partyArray = {&rival_first_encounter[0][0]}, .trainerId = 4}, //female easy
168
+    {.partyCount = 1, .partyArray = {&rival_first_encounter[0][0]}, .trainerId = 5}, //female medium
169
+    {.partyCount = 1, .partyArray = {&rival_first_encounter[0][0]}, .trainerId = 6}, //female hard
170
+};

+ 16
- 0
src/trainer/trainer_rival_encounters.h Целия файл

@@ -0,0 +1,16 @@
1
+#ifndef TRAINER_RIVAL_ENC_H_
2
+#define TRAINER_RIVAL_ENC_H_
3
+
4
+#include <pokeagb/pokeagb.h>
5
+
6
+#define RIVAL_ENCOUNTER_COUNT 6
7
+
8
+struct RivalEncounter {
9
+    u8 partyCount;
10
+    const union TrainerPokemonPtr partyArray;
11
+    u8 trainerId;
12
+};
13
+
14
+const struct RivalEncounter rival_encounters[RIVAL_ENCOUNTER_COUNT];
15
+
16
+#endif

+ 162
- 0
src/trainer/trainerbattle_init.c Целия файл

@@ -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
+}