dragonflysots 6 years ago
parent
commit
17f74d4ff8

+ 2
- 0
data/moves/move_data.s View File

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

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

+ 1
- 1
g3headers

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

+ 5
- 0
patches/overworlds/trainer.asm View File

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

+ 22
- 22
patches/trainer_sprites/trainer_data.asm View File

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

+ 0
- 16
src/overworld/trainerbattle_init.c View File

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 View File


+ 170
- 0
src/trainer/trainer_rival_encounters.c View File

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 View File

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 View File

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