Merge branch 'pagefaultgames:beta' into codespace-cuddly-system-x5pq7j974vwjc4pq
12
index.css
@ -164,13 +164,13 @@ input:-internal-autofill-selected {
|
||||
}
|
||||
|
||||
/* Show cycle buttons only on STARTER_SELECT and on touch configuration panel */
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT']) #apadOpenFilters,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='RUN_INFO']) #apadCycleForm,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='RUN_INFO']) #apadCycleShiny,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX'], [data-ui-mode='POKEDEX_PAGE']) #apadOpenFilters,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX'], [data-ui-mode='POKEDEX_PAGE'], [data-ui-mode='RUN_INFO']) #apadCycleForm,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX'], [data-ui-mode='POKEDEX_PAGE'], [data-ui-mode='RUN_INFO']) #apadCycleShiny,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT']) #apadCycleNature,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='RUN_INFO']) #apadCycleAbility,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT']) #apadCycleGender,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT']) #apadCycleVariant {
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX_PAGE'], [data-ui-mode='RUN_INFO']) #apadCycleAbility,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX_PAGE']) #apadCycleGender,
|
||||
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX']) #apadCycleVariant {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "pokemon-rogue-battle",
|
||||
"version": "1.5.4",
|
||||
"version": "1.7.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "pokemon-rogue-battle",
|
||||
"version": "1.5.4",
|
||||
"version": "1.7.0",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@material/material-color-utilities": "^0.2.7",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "pokemon-rogue-battle",
|
||||
"private": true,
|
||||
"version": "1.5.4",
|
||||
"version": "1.7.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
|
774
public/battle-anims/common-terastallize.json
Normal file
@ -0,0 +1,774 @@
|
||||
{
|
||||
"graphic": "terastallize",
|
||||
"frames": [
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 150,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 225,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 70,
|
||||
"zoomY": 70,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 70,
|
||||
"zoomY": 70,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 90,
|
||||
"zoomY": 90,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 90,
|
||||
"zoomY": 90,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 255,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 200,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 100,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 100,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 60,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 60,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": -20,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 2,
|
||||
"graphicFrame": 1,
|
||||
"opacity": 60,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
255
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
0
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 0,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"tone": [
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
255
|
||||
],
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 2
|
||||
},
|
||||
{
|
||||
"x": 128,
|
||||
"y": -64,
|
||||
"zoomX": 100,
|
||||
"zoomY": 100,
|
||||
"visible": true,
|
||||
"target": 1,
|
||||
"graphicFrame": 0,
|
||||
"opacity": 255,
|
||||
"locked": true,
|
||||
"priority": 1,
|
||||
"focus": 1
|
||||
}
|
||||
]
|
||||
],
|
||||
"frameTimedEvents": {},
|
||||
"position": 4,
|
||||
"hue": 0
|
||||
}
|
BIN
public/images/battle_anims/terastallize.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 24 KiB |
@ -1,41 +0,0 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "668-female.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 72,
|
||||
"h": 72
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0001.png",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 63,
|
||||
"h": 72
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 63,
|
||||
"h": 72
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 63,
|
||||
"h": 72
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:3f88e039152d4a967a218cb721938610:e6991ce9c3bad348cbc05ebf9b440302:d99ed0e84a0695b54e479aa98271aba1$"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 898 B |
BIN
public/images/pokemon/icons/7/802-zenith.png
Normal file
After Width: | Height: | Size: 396 B |
BIN
public/images/pokemon/icons/7/802s-zenith.png
Normal file
After Width: | Height: | Size: 396 B |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
158
public/images/ui/button_tera.json
Normal file
@ -0,0 +1,158 @@
|
||||
{ "frames": {
|
||||
"unknown": {
|
||||
"frame": { "x": 0, "y": 0, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"bug": {
|
||||
"frame": { "x": 18, "y": 0, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"dark": {
|
||||
"frame": { "x": 36, "y": 0, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"dragon": {
|
||||
"frame": { "x": 54, "y": 0, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"electric": {
|
||||
"frame": { "x": 72, "y": 0, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"fairy": {
|
||||
"frame": { "x": 0, "y": 21, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"fighting": {
|
||||
"frame": { "x": 18, "y": 21, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"fire": {
|
||||
"frame": { "x": 36, "y": 21, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"flying": {
|
||||
"frame": { "x": 54, "y": 21, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"ghost": {
|
||||
"frame": { "x": 72, "y": 21, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"grass": {
|
||||
"frame": { "x": 0, "y": 42, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"ground": {
|
||||
"frame": { "x": 18, "y": 42, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"ice": {
|
||||
"frame": { "x": 36, "y": 42, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"normal": {
|
||||
"frame": { "x": 54, "y": 42, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"poison": {
|
||||
"frame": { "x": 72, "y": 42, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"psychic": {
|
||||
"frame": { "x": 0, "y": 63, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"rock": {
|
||||
"frame": { "x": 18, "y": 63, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"steel": {
|
||||
"frame": { "x": 36, "y": 63, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"water": {
|
||||
"frame": { "x": 54, "y": 63, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"stellar": {
|
||||
"frame": { "x": 72, "y": 63, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"app": "https://www.aseprite.org/",
|
||||
"version": "1.3.7-dev",
|
||||
"image": "button_tera.png",
|
||||
"format": "RGBA8888",
|
||||
"size": { "w": 90, "h": 84 },
|
||||
"scale": "1",
|
||||
"frameTags": [
|
||||
],
|
||||
"layers": [
|
||||
{ "name": "Sprite Sheet", "opacity": 255, "blendMode": "normal" }
|
||||
],
|
||||
"slices": [
|
||||
]
|
||||
}
|
||||
}
|
BIN
public/images/ui/button_tera.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
158
public/images/ui/legacy/button_tera.json
Normal file
@ -0,0 +1,158 @@
|
||||
{ "frames": {
|
||||
"unknown": {
|
||||
"frame": { "x": 0, "y": 0, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"bug": {
|
||||
"frame": { "x": 18, "y": 0, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"dark": {
|
||||
"frame": { "x": 36, "y": 0, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"dragon": {
|
||||
"frame": { "x": 54, "y": 0, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"electric": {
|
||||
"frame": { "x": 72, "y": 0, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"fairy": {
|
||||
"frame": { "x": 0, "y": 21, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"fighting": {
|
||||
"frame": { "x": 18, "y": 21, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"fire": {
|
||||
"frame": { "x": 36, "y": 21, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"flying": {
|
||||
"frame": { "x": 54, "y": 21, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"ghost": {
|
||||
"frame": { "x": 72, "y": 21, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"grass": {
|
||||
"frame": { "x": 0, "y": 42, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"ground": {
|
||||
"frame": { "x": 18, "y": 42, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"ice": {
|
||||
"frame": { "x": 36, "y": 42, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"normal": {
|
||||
"frame": { "x": 54, "y": 42, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"poison": {
|
||||
"frame": { "x": 72, "y": 42, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"psychic": {
|
||||
"frame": { "x": 0, "y": 63, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"rock": {
|
||||
"frame": { "x": 18, "y": 63, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"steel": {
|
||||
"frame": { "x": 36, "y": 63, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"water": {
|
||||
"frame": { "x": 54, "y": 63, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
},
|
||||
"stellar": {
|
||||
"frame": { "x": 72, "y": 63, "w": 18, "h": 21 },
|
||||
"rotated": false,
|
||||
"trimmed": true,
|
||||
"spriteSourceSize": { "x": 1, "y": 1, "w": 18, "h": 21 },
|
||||
"sourceSize": { "w": 20, "h": 23 }
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"app": "https://www.aseprite.org/",
|
||||
"version": "1.3.7-dev",
|
||||
"image": "button_tera.png",
|
||||
"format": "RGBA8888",
|
||||
"size": { "w": 90, "h": 84 },
|
||||
"scale": "1",
|
||||
"frameTags": [
|
||||
],
|
||||
"layers": [
|
||||
{ "name": "Sprite Sheet", "opacity": 255, "blendMode": "normal" }
|
||||
],
|
||||
"slices": [
|
||||
]
|
||||
}
|
||||
}
|
BIN
public/images/ui/legacy/button_tera.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
@ -1 +1 @@
|
||||
Subproject commit bfcd7f91c39630f155839872c8f66fd0a89e12ac
|
||||
Subproject commit 58dda14ee834204c4bd5ece47694a3c068df4b0e
|
@ -9,7 +9,7 @@ import type { Constructor } from "#app/utils";
|
||||
import { isNullOrUndefined, randSeedInt } from "#app/utils";
|
||||
import * as Utils from "#app/utils";
|
||||
import type { Modifier, ModifierPredicate, TurnHeldItemTransferModifier } from "./modifier/modifier";
|
||||
import { ConsumableModifier, ConsumablePokemonModifier, DoubleBattleChanceBoosterModifier, ExpBalanceModifier, ExpShareModifier, FusePokemonModifier, HealingBoosterModifier, ModifierBar, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, RememberMoveModifier, TerastallizeModifier } from "./modifier/modifier";
|
||||
import { ConsumableModifier, ConsumablePokemonModifier, DoubleBattleChanceBoosterModifier, ExpBalanceModifier, ExpShareModifier, FusePokemonModifier, HealingBoosterModifier, ModifierBar, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, RememberMoveModifier } from "./modifier/modifier";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "#app/data/battle-anims";
|
||||
import type { Phase } from "#app/phase";
|
||||
@ -1212,7 +1212,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
getDoubleBattleChance(newWaveIndex: number, playerField: PlayerPokemon[]) {
|
||||
const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8);
|
||||
const doubleChance = new Utils.NumberHolder(newWaveIndex % 10 === 0 ? 32 : 8);
|
||||
this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance);
|
||||
playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance));
|
||||
return Math.max(doubleChance.value, 1);
|
||||
@ -1373,7 +1373,11 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
for (const pokemon of this.getPlayerParty()) {
|
||||
pokemon.resetBattleData();
|
||||
pokemon.resetTera();
|
||||
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon);
|
||||
if (pokemon.hasSpecies(Species.TERAPAGOS) || (this.gameMode.isClassic && this.currentBattle.waveIndex > 180 && this.currentBattle.waveIndex <= 190)) {
|
||||
this.arena.playerTerasUsed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.trainer.visible) {
|
||||
@ -1658,7 +1662,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
initPokemonSprite(sprite: Phaser.GameObjects.Sprite, pokemon?: Pokemon, hasShadow: boolean = false, ignoreOverride: boolean = false): Phaser.GameObjects.Sprite {
|
||||
sprite.setPipeline(this.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: hasShadow, ignoreOverride: ignoreOverride, teraColor: pokemon ? getTypeRgb(pokemon.getTeraType()) : undefined });
|
||||
sprite.setPipeline(this.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: hasShadow, ignoreOverride: ignoreOverride, teraColor: pokemon ? getTypeRgb(pokemon.getTeraType()) : undefined, isTerastallized: pokemon ? pokemon.isTerastallized : false });
|
||||
this.spriteSparkleHandler.add(sprite);
|
||||
return sprite;
|
||||
}
|
||||
@ -2589,11 +2593,8 @@ export default class BattleScene extends SceneBase {
|
||||
const modifiersToRemove: PersistentModifier[] = [];
|
||||
const modifierPromises: Promise<boolean>[] = [];
|
||||
if (modifier instanceof PersistentModifier) {
|
||||
if (modifier instanceof TerastallizeModifier) {
|
||||
modifiersToRemove.push(...(this.findModifiers(m => m instanceof TerastallizeModifier && m.pokemonId === modifier.pokemonId)));
|
||||
}
|
||||
if ((modifier as PersistentModifier).add(this.modifiers, !!virtual)) {
|
||||
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) {
|
||||
if (modifier instanceof PokemonFormChangeItemModifier) {
|
||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||
if (pokemon) {
|
||||
success = modifier.apply(pokemon, true);
|
||||
@ -2627,7 +2628,7 @@ export default class BattleScene extends SceneBase {
|
||||
const args: unknown[] = [];
|
||||
if (modifier instanceof PokemonHpRestoreModifier) {
|
||||
if (!(modifier as PokemonHpRestoreModifier).fainted) {
|
||||
const hpRestoreMultiplier = new Utils.IntegerHolder(1);
|
||||
const hpRestoreMultiplier = new Utils.NumberHolder(1);
|
||||
this.applyModifiers(HealingBoosterModifier, true, hpRestoreMultiplier);
|
||||
args.push(hpRestoreMultiplier.value);
|
||||
} else {
|
||||
@ -2670,11 +2671,8 @@ export default class BattleScene extends SceneBase {
|
||||
addEnemyModifier(modifier: PersistentModifier, ignoreUpdate?: boolean, instant?: boolean): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
const modifiersToRemove: PersistentModifier[] = [];
|
||||
if (modifier instanceof TerastallizeModifier) {
|
||||
modifiersToRemove.push(...(this.findModifiers(m => m instanceof TerastallizeModifier && m.pokemonId === modifier.pokemonId, false)));
|
||||
}
|
||||
if ((modifier as PersistentModifier).add(this.enemyModifiers, false)) {
|
||||
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) {
|
||||
if (modifier instanceof PokemonFormChangeItemModifier) {
|
||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||
if (pokemon) {
|
||||
modifier.apply(pokemon, true);
|
||||
@ -2798,6 +2796,8 @@ export default class BattleScene extends SceneBase {
|
||||
for (const modifier of modifiers) {
|
||||
this.addEnemyModifier(modifier, true, true);
|
||||
}
|
||||
|
||||
this.currentBattle.trainer.genAI(party);
|
||||
}
|
||||
|
||||
party.forEach((enemyPokemon: EnemyPokemon, i: number) => {
|
||||
@ -2929,7 +2929,7 @@ export default class BattleScene extends SceneBase {
|
||||
const modifierIndex = modifiers.indexOf(modifier);
|
||||
if (modifierIndex > -1) {
|
||||
modifiers.splice(modifierIndex, 1);
|
||||
if (modifier instanceof PokemonFormChangeItemModifier || modifier instanceof TerastallizeModifier) {
|
||||
if (modifier instanceof PokemonFormChangeItemModifier) {
|
||||
const pokemon = this.getPokemonById(modifier.pokemonId);
|
||||
if (pokemon) {
|
||||
modifier.apply(pokemon, false);
|
||||
@ -3130,7 +3130,8 @@ export default class BattleScene extends SceneBase {
|
||||
name: p.name,
|
||||
form: p.getFormKey(),
|
||||
types: p.getTypes().map((type) => Type[type]),
|
||||
teraType: p.getTeraType() !== Type.UNKNOWN ? Type[p.getTeraType()] : "",
|
||||
teraType: Type[p.getTeraType()],
|
||||
isTerastallized: p.isTerastallized,
|
||||
level: p.level,
|
||||
currentHP: p.hp,
|
||||
maxHP: p.getMaxHp(),
|
||||
|
@ -92,6 +92,7 @@ export default class Battle {
|
||||
public started: boolean = false;
|
||||
public enemySwitchCounter: number = 0;
|
||||
public turn: number = 0;
|
||||
public preTurnCommands: TurnCommands;
|
||||
public turnCommands: TurnCommands;
|
||||
public playerParticipantIds: Set<number> = new Set<number>();
|
||||
public battleScore: number = 0;
|
||||
@ -180,6 +181,7 @@ export default class Battle {
|
||||
incrementTurn(): void {
|
||||
this.turn++;
|
||||
this.turnCommands = Object.fromEntries(Utils.getEnumValues(BattlerIndex).map(bt => [ bt, null ]));
|
||||
this.preTurnCommands = Object.fromEntries(Utils.getEnumValues(BattlerIndex).map(bt => [ bt, null ]));
|
||||
this.battleSeedState = null;
|
||||
}
|
||||
|
||||
@ -201,7 +203,7 @@ export default class Battle {
|
||||
}
|
||||
|
||||
pickUpScatteredMoney(): void {
|
||||
const moneyAmount = new Utils.IntegerHolder(globalScene.currentBattle.moneyScattered);
|
||||
const moneyAmount = new Utils.NumberHolder(globalScene.currentBattle.moneyScattered);
|
||||
globalScene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount);
|
||||
|
||||
if (globalScene.arena.getTag(ArenaTagType.HAPPY_HOUR)) {
|
||||
|
@ -239,37 +239,25 @@ export class PostBattleInitFormChangeAbAttr extends PostBattleInitAbAttr {
|
||||
}
|
||||
}
|
||||
|
||||
export class PostBattleInitStatStageChangeAbAttr extends PostBattleInitAbAttr {
|
||||
export class PostTeraFormChangeStatChangeAbAttr extends AbAttr {
|
||||
private stats: BattleStat[];
|
||||
private stages: number;
|
||||
private selfTarget: boolean;
|
||||
|
||||
constructor(stats: BattleStat[], stages: number, selfTarget?: boolean) {
|
||||
constructor(stats: BattleStat[], stages: number) {
|
||||
super();
|
||||
|
||||
this.stats = stats;
|
||||
this.stages = stages;
|
||||
this.selfTarget = !!selfTarget;
|
||||
}
|
||||
|
||||
applyPostBattleInit(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||
apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder | null, args: any[]): boolean | Promise<boolean> {
|
||||
const statStageChangePhases: StatStageChangePhase[] = [];
|
||||
|
||||
if (!simulated) {
|
||||
if (this.selfTarget) {
|
||||
statStageChangePhases.push(new StatStageChangePhase(pokemon.getBattlerIndex(), true, this.stats, this.stages));
|
||||
} else {
|
||||
for (const opponent of pokemon.getOpponents()) {
|
||||
statStageChangePhases.push(new StatStageChangePhase(opponent.getBattlerIndex(), false, this.stats, this.stages));
|
||||
}
|
||||
}
|
||||
statStageChangePhases.push(new StatStageChangePhase(pokemon.getBattlerIndex(), true, this.stats, this.stages));
|
||||
|
||||
for (const statStageChangePhase of statStageChangePhases) {
|
||||
if (!this.selfTarget && !statStageChangePhase.getPokemon()?.summonData) {
|
||||
globalScene.pushPhase(statStageChangePhase);
|
||||
} else { // TODO: This causes the ability bar to be shown at the wrong time
|
||||
globalScene.unshiftPhase(statStageChangePhase);
|
||||
}
|
||||
globalScene.unshiftPhase(statStageChangePhase);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1307,7 +1295,7 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr {
|
||||
|
||||
applyPreAttack(pokemon: Pokemon, passive: boolean, simulated: boolean, defender: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (
|
||||
!pokemon.isTerastallized() &&
|
||||
!pokemon.isTerastallized &&
|
||||
move.id !== Moves.STRUGGLE &&
|
||||
/**
|
||||
* Skip moves that call other moves because these moves generate a following move that will trigger this ability attribute
|
||||
@ -3127,7 +3115,7 @@ export class ChangeMovePriorityAbAttr extends AbAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
(args[1] as Utils.IntegerHolder).value += this.changeAmount;
|
||||
(args[1] as Utils.NumberHolder).value += this.changeAmount;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3969,7 +3957,7 @@ export class StatStageChangeMultiplierAbAttr extends AbAttr {
|
||||
}
|
||||
|
||||
override apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value *= this.multiplier;
|
||||
(args[0] as Utils.NumberHolder).value *= this.multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -4070,7 +4058,7 @@ export class HealFromBerryUseAbAttr extends AbAttr {
|
||||
|
||||
export class RunSuccessAbAttr extends AbAttr {
|
||||
apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value = 256;
|
||||
(args[0] as Utils.NumberHolder).value = 256;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -4140,7 +4128,7 @@ export class ArenaTrapAbAttr extends CheckTrappedAbAttr {
|
||||
|
||||
export class MaxMultiHitAbAttr extends AbAttr {
|
||||
apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value = 0;
|
||||
(args[0] as Utils.NumberHolder).value = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -4271,7 +4259,7 @@ export class PostFaintHPDamageAbAttr extends PostFaintAbAttr {
|
||||
export class RedirectMoveAbAttr extends AbAttr {
|
||||
apply(pokemon: Pokemon, passive: boolean, simulated: boolean, cancelled: Utils.BooleanHolder, args: any[]): boolean {
|
||||
if (this.canRedirect(args[0] as Moves)) {
|
||||
const target = args[1] as Utils.IntegerHolder;
|
||||
const target = args[1] as Utils.NumberHolder;
|
||||
const newTarget = pokemon.getBattlerIndex();
|
||||
if (target.value !== newTarget) {
|
||||
target.value = newTarget;
|
||||
@ -4788,7 +4776,7 @@ export class TerrainEventTypeChangeAbAttr extends PostSummonAbAttr {
|
||||
}
|
||||
|
||||
override apply(pokemon: Pokemon, _passive: boolean, _simulated: boolean, _cancelled: Utils.BooleanHolder, _args: any[]): boolean {
|
||||
if (pokemon.isTerastallized()) {
|
||||
if (pokemon.isTerastallized) {
|
||||
return false;
|
||||
}
|
||||
const currentTerrain = globalScene.arena.getTerrainType();
|
||||
@ -6201,7 +6189,7 @@ export function initAbilities() {
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.condition((pokemon) => !pokemon.isTerastallized()),
|
||||
.condition((pokemon) => !pokemon.isTerastallized),
|
||||
new Ability(Abilities.QUICK_DRAW, 8)
|
||||
.attr(BypassSpeedChanceAbAttr, 30),
|
||||
new Ability(Abilities.UNSEEN_FIST, 8)
|
||||
@ -6285,15 +6273,13 @@ export function initAbilities() {
|
||||
.attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.PROTOSYNTHESIS, 0, WeatherType.SUNNY, WeatherType.HARSH_SUN)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(), // While setting the tag, the getbattlestat should ignore all modifiers to stats except stat stages
|
||||
.attr(NoTransformAbilityAbAttr),
|
||||
new Ability(Abilities.QUARK_DRIVE, 9)
|
||||
.conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), PostSummonAddBattlerTagAbAttr, BattlerTagType.QUARK_DRIVE, 0, true)
|
||||
.attr(PostTerrainChangeAddBattlerTagAttr, BattlerTagType.QUARK_DRIVE, 0, TerrainType.ELECTRIC)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(), // While setting the tag, the getbattlestat should ignore all modifiers to stats except stat stages
|
||||
.attr(NoTransformAbilityAbAttr),
|
||||
new Ability(Abilities.GOOD_AS_GOLD, 9)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS && ![ MoveTarget.ENEMY_SIDE, MoveTarget.BOTH_SIDES, MoveTarget.USER_SIDE ].includes(move.moveTarget))
|
||||
.ignorable(),
|
||||
@ -6355,29 +6341,25 @@ export function initAbilities() {
|
||||
new Ability(Abilities.TOXIC_CHAIN, 9)
|
||||
.attr(PostAttackApplyStatusEffectAbAttr, false, 30, StatusEffect.TOXIC),
|
||||
new Ability(Abilities.EMBODY_ASPECT_TEAL, 9)
|
||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.SPD ], 1, true)
|
||||
.attr(PostTeraFormChangeStatChangeAbAttr, [ Stat.SPD ], 1)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(), // Ogerpon tera interactions
|
||||
.attr(NoTransformAbilityAbAttr),
|
||||
new Ability(Abilities.EMBODY_ASPECT_WELLSPRING, 9)
|
||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.SPDEF ], 1, true)
|
||||
.attr(PostTeraFormChangeStatChangeAbAttr, [ Stat.SPDEF ], 1)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(), // Ogerpon tera interactions
|
||||
.attr(NoTransformAbilityAbAttr),
|
||||
new Ability(Abilities.EMBODY_ASPECT_HEARTHFLAME, 9)
|
||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.ATK ], 1, true)
|
||||
.attr(PostTeraFormChangeStatChangeAbAttr, [ Stat.ATK ], 1)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(), // Ogerpon tera interactions
|
||||
.attr(NoTransformAbilityAbAttr),
|
||||
new Ability(Abilities.EMBODY_ASPECT_CORNERSTONE, 9)
|
||||
.attr(PostBattleInitStatStageChangeAbAttr, [ Stat.DEF ], 1, true)
|
||||
.attr(PostTeraFormChangeStatChangeAbAttr, [ Stat.DEF ], 1)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.partial(), // Ogerpon tera interactions
|
||||
.attr(NoTransformAbilityAbAttr),
|
||||
new Ability(Abilities.TERA_SHIFT, 9)
|
||||
.attr(PostSummonFormChangeAbAttr, p => p.getFormKey() ? 0 : 1)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
|
@ -56,6 +56,7 @@ export enum ChargeAnim {
|
||||
export enum CommonAnim {
|
||||
USE_ITEM = 2000,
|
||||
HEALTH_UP,
|
||||
TERASTALLIZE,
|
||||
POISON = 2010,
|
||||
TOXIC,
|
||||
PARALYSIS,
|
||||
|
@ -2485,7 +2485,7 @@ export class TarShotTag extends BattlerTag {
|
||||
* @returns whether the tag is applied
|
||||
*/
|
||||
override canAdd(pokemon: Pokemon): boolean {
|
||||
return !pokemon.isTerastallized();
|
||||
return !pokemon.isTerastallized;
|
||||
}
|
||||
|
||||
override onAdd(pokemon: Pokemon): void {
|
||||
|
@ -349,23 +349,23 @@ export abstract class Challenge {
|
||||
|
||||
/**
|
||||
* An apply function for AI_LEVEL challenges. Derived classes should alter this.
|
||||
* @param level {@link Utils.IntegerHolder} The generated level.
|
||||
* @param level {@link Utils.NumberHolder} The generated level.
|
||||
* @param levelCap {@link Number} The current level cap.
|
||||
* @param isTrainer {@link Boolean} Whether this is a trainer pokemon.
|
||||
* @param isBoss {@link Boolean} Whether this is a non-trainer boss pokemon.
|
||||
* @returns {@link boolean} Whether this function did anything.
|
||||
*/
|
||||
applyLevelChange(level: Utils.IntegerHolder, levelCap: number, isTrainer: boolean, isBoss: boolean): boolean {
|
||||
applyLevelChange(level: Utils.NumberHolder, levelCap: number, isTrainer: boolean, isBoss: boolean): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An apply function for AI_MOVE_SLOTS challenges. Derived classes should alter this.
|
||||
* @param pokemon {@link Pokemon} The pokemon that is being considered.
|
||||
* @param moveSlots {@link Utils.IntegerHolder} The amount of move slots.
|
||||
* @param moveSlots {@link Utils.NumberHolder} The amount of move slots.
|
||||
* @returns {@link boolean} Whether this function did anything.
|
||||
*/
|
||||
applyMoveSlot(pokemon: Pokemon, moveSlots: Utils.IntegerHolder): boolean {
|
||||
applyMoveSlot(pokemon: Pokemon, moveSlots: Utils.NumberHolder): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -393,10 +393,10 @@ export abstract class Challenge {
|
||||
* @param pokemon {@link Pokemon} What pokemon would learn the move.
|
||||
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
||||
* @param move {@link Moves} The move in question.
|
||||
* @param level {@link Utils.IntegerHolder} The level threshold for access.
|
||||
* @param level {@link Utils.NumberHolder} The level threshold for access.
|
||||
* @returns {@link boolean} Whether this function did anything.
|
||||
*/
|
||||
applyMoveAccessLevel(pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.IntegerHolder): boolean {
|
||||
applyMoveAccessLevel(pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.NumberHolder): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -405,10 +405,10 @@ export abstract class Challenge {
|
||||
* @param pokemon {@link Pokemon} What pokemon would learn the move.
|
||||
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
||||
* @param move {@link Moves} The move in question.
|
||||
* @param weight {@link Utils.IntegerHolder} The base weight of the move
|
||||
* @param weight {@link Utils.NumberHolder} The base weight of the move
|
||||
* @returns {@link boolean} Whether this function did anything.
|
||||
*/
|
||||
applyMoveWeight(pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.IntegerHolder): boolean {
|
||||
applyMoveWeight(pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.NumberHolder): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -456,8 +456,8 @@ export class SingleGenerationChallenge extends Challenge {
|
||||
}
|
||||
|
||||
applyPokemonInBattle(pokemon: Pokemon, valid: Utils.BooleanHolder): boolean {
|
||||
const baseGeneration = pokemon.species.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.species.speciesId).generation;
|
||||
const fusionGeneration = pokemon.isFusion() ? pokemon.fusionSpecies?.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.fusionSpecies!.speciesId).generation : 0; // TODO: is the bang on fusionSpecies correct?
|
||||
const baseGeneration = getPokemonSpecies(pokemon.species.speciesId).generation;
|
||||
const fusionGeneration = pokemon.isFusion() ? getPokemonSpecies(pokemon.fusionSpecies!.speciesId).generation : 0; // TODO: is the bang on fusionSpecies correct?
|
||||
if (pokemon.isPlayer() && (baseGeneration !== this.value || (pokemon.isFusion() && fusionGeneration !== this.value))) {
|
||||
valid.value = false;
|
||||
return true;
|
||||
@ -913,22 +913,22 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
|
||||
* Apply all challenges that modify what level AI are.
|
||||
* @param gameMode {@link GameMode} The current gameMode
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.AI_LEVEL
|
||||
* @param level {@link Utils.IntegerHolder} The generated level of the pokemon.
|
||||
* @param level {@link Utils.NumberHolder} The generated level of the pokemon.
|
||||
* @param levelCap {@link Number} The maximum level cap for the current wave.
|
||||
* @param isTrainer {@link Boolean} Whether this is a trainer pokemon.
|
||||
* @param isBoss {@link Boolean} Whether this is a non-trainer boss pokemon.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.AI_LEVEL, level: Utils.IntegerHolder, levelCap: number, isTrainer: boolean, isBoss: boolean): boolean;
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.AI_LEVEL, level: Utils.NumberHolder, levelCap: number, isTrainer: boolean, isBoss: boolean): boolean;
|
||||
/**
|
||||
* Apply all challenges that modify how many move slots the AI has.
|
||||
* @param gameMode {@link GameMode} The current gameMode
|
||||
* @param challengeType {@link ChallengeType} ChallengeType.AI_MOVE_SLOTS
|
||||
* @param pokemon {@link Pokemon} The pokemon being considered.
|
||||
* @param moveSlots {@link Utils.IntegerHolder} The amount of move slots.
|
||||
* @param moveSlots {@link Utils.NumberHolder} The amount of move slots.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.AI_MOVE_SLOTS, pokemon: Pokemon, moveSlots: Utils.IntegerHolder): boolean;
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.AI_MOVE_SLOTS, pokemon: Pokemon, moveSlots: Utils.NumberHolder): boolean;
|
||||
/**
|
||||
* Apply all challenges that modify whether a pokemon has its passive.
|
||||
* @param gameMode {@link GameMode} The current gameMode
|
||||
@ -952,10 +952,10 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
|
||||
* @param pokemon {@link Pokemon} What pokemon would learn the move.
|
||||
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
||||
* @param move {@link Moves} The move in question.
|
||||
* @param level {@link Utils.IntegerHolder} The level threshold for access.
|
||||
* @param level {@link Utils.NumberHolder} The level threshold for access.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.MOVE_ACCESS, pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.IntegerHolder): boolean;
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.MOVE_ACCESS, pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.NumberHolder): boolean;
|
||||
/**
|
||||
* Apply all challenges that modify what weight a pokemon gives to move generation
|
||||
* @param gameMode {@link GameMode} The current gameMode
|
||||
@ -963,10 +963,10 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
|
||||
* @param pokemon {@link Pokemon} What pokemon would learn the move.
|
||||
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
|
||||
* @param move {@link Moves} The move in question.
|
||||
* @param weight {@link Utils.IntegerHolder} The weight of the move.
|
||||
* @param weight {@link Utils.NumberHolder} The weight of the move.
|
||||
* @returns True if any challenge was successfully applied.
|
||||
*/
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.MOVE_WEIGHT, pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, weight: Utils.IntegerHolder): boolean;
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.MOVE_WEIGHT, pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, weight: Utils.NumberHolder): boolean;
|
||||
|
||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.FLIP_STAT, pokemon: Pokemon, baseStats: number[]): boolean;
|
||||
|
||||
|
104
src/data/move.ts
@ -791,7 +791,7 @@ export default class Move implements Localizable {
|
||||
applyPreAttackAbAttrs(MoveTypeChangeAbAttr, source, target, this, true, null, typeChangeMovePowerMultiplier);
|
||||
|
||||
const sourceTeraType = source.getTeraType();
|
||||
if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === this.type && power.value < 60 && this.priority <= 0 && !this.hasAttr(MultiHitAttr) && !globalScene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id)) {
|
||||
if (source.isTerastallized && sourceTeraType === this.type && power.value < 60 && this.priority <= 0 && !this.hasAttr(MultiHitAttr) && !globalScene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id)) {
|
||||
power.value = 60;
|
||||
}
|
||||
|
||||
@ -908,7 +908,7 @@ export class AttackMove extends Move {
|
||||
attackScore = Math.pow(effectiveness - 1, 2) * effectiveness < 1 ? -2 : 2;
|
||||
if (attackScore) {
|
||||
if (this.category === MoveCategory.PHYSICAL) {
|
||||
const atk = new Utils.IntegerHolder(user.getEffectiveStat(Stat.ATK, target));
|
||||
const atk = new Utils.NumberHolder(user.getEffectiveStat(Stat.ATK, target));
|
||||
applyMoveAttrs(VariableAtkAttr, user, target, move, atk);
|
||||
if (atk.value > user.getEffectiveStat(Stat.SPATK, target)) {
|
||||
const statRatio = user.getEffectiveStat(Stat.SPATK, target) / atk.value;
|
||||
@ -919,7 +919,7 @@ export class AttackMove extends Move {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const spAtk = new Utils.IntegerHolder(user.getEffectiveStat(Stat.SPATK, target));
|
||||
const spAtk = new Utils.NumberHolder(user.getEffectiveStat(Stat.SPATK, target));
|
||||
applyMoveAttrs(VariableAtkAttr, user, target, move, spAtk);
|
||||
if (spAtk.value > user.getEffectiveStat(Stat.ATK, target)) {
|
||||
const statRatio = user.getEffectiveStat(Stat.ATK, target) / spAtk.value;
|
||||
@ -1337,7 +1337,7 @@ export class IgnoreOpponentStatStagesAttr extends MoveAttr {
|
||||
|
||||
export class HighCritAttr extends MoveAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value++;
|
||||
(args[0] as Utils.NumberHolder).value++;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1369,7 +1369,7 @@ export class FixedDamageAttr extends MoveAttr {
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value = this.getDamage(user, target, move);
|
||||
(args[0] as Utils.NumberHolder).value = this.getDamage(user, target, move);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1385,7 +1385,7 @@ export class UserHpDamageAttr extends FixedDamageAttr {
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value = user.hp;
|
||||
(args[0] as Utils.NumberHolder).value = user.hp;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1437,7 +1437,7 @@ export class MatchHpAttr extends FixedDamageAttr {
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value = target.hp - user.hp;
|
||||
(args[0] as Utils.NumberHolder).value = target.hp - user.hp;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1467,7 +1467,7 @@ export class CounterDamageAttr extends FixedDamageAttr {
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const damage = user.turnData.attacksReceived.filter(ar => this.moveFilter(allMoves[ar.move])).reduce((total: number, ar: AttackMoveResult) => total + ar.damage, 0);
|
||||
(args[0] as Utils.IntegerHolder).value = Utils.toDmgValue(damage * this.multiplier);
|
||||
(args[0] as Utils.NumberHolder).value = Utils.toDmgValue(damage * this.multiplier);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1499,7 +1499,7 @@ export class RandomLevelDamageAttr extends FixedDamageAttr {
|
||||
|
||||
export class ModifiedDamageAttr extends MoveAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const initialDamage = args[0] as Utils.IntegerHolder;
|
||||
const initialDamage = args[0] as Utils.NumberHolder;
|
||||
initialDamage.value = this.getModifiedDamage(user, target, move, initialDamage.value);
|
||||
|
||||
return true;
|
||||
@ -2164,7 +2164,7 @@ export class IncrementMovePriorityAttr extends MoveAttr {
|
||||
* @param user {@linkcode Pokemon} using this move
|
||||
* @param target {@linkcode Pokemon} target of this move
|
||||
* @param move {@linkcode Move} being used
|
||||
* @param args [0] {@linkcode Utils.IntegerHolder} for move priority.
|
||||
* @param args [0] {@linkcode Utils.NumberHolder} for move priority.
|
||||
* @returns true if function succeeds
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
@ -2172,7 +2172,7 @@ export class IncrementMovePriorityAttr extends MoveAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
(args[0] as Utils.IntegerHolder).value += this.increaseAmount;
|
||||
(args[0] as Utils.NumberHolder).value += this.increaseAmount;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2210,7 +2210,7 @@ export class MultiHitAttr extends MoveAttr {
|
||||
* @param user {@linkcode Pokemon} that used the attack
|
||||
* @param target {@linkcode Pokemon} targeted by the attack
|
||||
* @param move {@linkcode Move} being used
|
||||
* @param args [0] {@linkcode Utils.IntegerHolder} storing the hit count of the attack
|
||||
* @param args [0] {@linkcode Utils.NumberHolder} storing the hit count of the attack
|
||||
* @returns True
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
@ -2277,7 +2277,7 @@ export class ChangeMultiHitTypeAttr extends MoveAttr {
|
||||
export class WaterShurikenMultiHitTypeAttr extends ChangeMultiHitTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (user.species.speciesId === Species.GRENINJA && user.hasAbility(Abilities.BATTLE_BOND) && user.formIndex === 2) {
|
||||
(args[0] as Utils.IntegerHolder).value = MultiHitType._3;
|
||||
(args[0] as Utils.NumberHolder).value = MultiHitType._3;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -4118,7 +4118,7 @@ export class PresentPowerAttr extends VariablePowerAttr {
|
||||
export class WaterShurikenPowerAttr extends VariablePowerAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (user.species.speciesId === Species.GRENINJA && user.hasAbility(Abilities.BATTLE_BOND) && user.formIndex === 2) {
|
||||
(args[0] as Utils.IntegerHolder).value = 20;
|
||||
(args[0] as Utils.NumberHolder).value = 20;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -4140,7 +4140,7 @@ export class SpitUpPowerAttr extends VariablePowerAttr {
|
||||
const stockpilingTag = user.getTag(StockpilingTag);
|
||||
|
||||
if (stockpilingTag && stockpilingTag.stockpiledCount > 0) {
|
||||
const power = args[0] as Utils.IntegerHolder;
|
||||
const power = args[0] as Utils.NumberHolder;
|
||||
power.value = this.multiplier * stockpilingTag.stockpiledCount;
|
||||
return true;
|
||||
}
|
||||
@ -4449,7 +4449,7 @@ export class VariableAtkAttr extends MoveAttr {
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
//const atk = args[0] as Utils.IntegerHolder;
|
||||
//const atk = args[0] as Utils.NumberHolder;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -4459,7 +4459,7 @@ export class TargetAtkUserAtkAttr extends VariableAtkAttr {
|
||||
super();
|
||||
}
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value = target.getEffectiveStat(Stat.ATK, target);
|
||||
(args[0] as Utils.NumberHolder).value = target.getEffectiveStat(Stat.ATK, target);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -4470,7 +4470,7 @@ export class DefAtkAttr extends VariableAtkAttr {
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value = user.getEffectiveStat(Stat.DEF, target);
|
||||
(args[0] as Utils.NumberHolder).value = user.getEffectiveStat(Stat.DEF, target);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -4481,7 +4481,7 @@ export class VariableDefAttr extends MoveAttr {
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
//const def = args[0] as Utils.IntegerHolder;
|
||||
//const def = args[0] as Utils.NumberHolder;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -4492,7 +4492,7 @@ export class DefDefAttr extends VariableDefAttr {
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
(args[0] as Utils.IntegerHolder).value = target.getEffectiveStat(Stat.DEF, user);
|
||||
(args[0] as Utils.NumberHolder).value = target.getEffectiveStat(Stat.DEF, user);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -4634,7 +4634,7 @@ export class TeraMoveCategoryAttr extends VariableMoveCategoryAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const category = (args[0] as Utils.NumberHolder);
|
||||
|
||||
if (user.isTerastallized() && user.getEffectiveStat(Stat.ATK, target, move, true, true, false, false, true) >
|
||||
if (user.isTerastallized && user.getEffectiveStat(Stat.ATK, target, move, true, true, false, false, true) >
|
||||
user.getEffectiveStat(Stat.SPATK, target, move, true, true, false, false, true)) {
|
||||
category.value = MoveCategory.PHYSICAL;
|
||||
return true;
|
||||
@ -4662,7 +4662,7 @@ export class TeraBlastPowerAttr extends VariablePowerAttr {
|
||||
*/
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const power = args[0] as Utils.NumberHolder;
|
||||
if (user.isTerastallized() && user.getTeraType() === Type.STELLAR) {
|
||||
if (user.isTerastallized && user.getTeraType() === Type.STELLAR) {
|
||||
power.value = 100;
|
||||
return true;
|
||||
}
|
||||
@ -4720,30 +4720,6 @@ export class VariableMoveTypeAttr extends MoveAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute used for Tera Starstorm that changes the move type to Stellar
|
||||
* @extends VariableMoveTypeAttr
|
||||
*/
|
||||
export class TeraStarstormTypeAttr extends VariableMoveTypeAttr {
|
||||
/**
|
||||
*
|
||||
* @param user the {@linkcode Pokemon} using the move
|
||||
* @param target n/a
|
||||
* @param move n/a
|
||||
* @param args[0] {@linkcode Utils.NumberHolder} the move type
|
||||
* @returns `true` if the move type is changed to {@linkcode Type.STELLAR}, `false` otherwise
|
||||
*/
|
||||
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (user.isTerastallized() && (user.hasFusionSpecies(Species.TERAPAGOS) || user.species.speciesId === Species.TERAPAGOS)) {
|
||||
const moveType = args[0] as Utils.NumberHolder;
|
||||
|
||||
moveType.value = Type.STELLAR;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class FormChangeItemTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const moveType = args[0];
|
||||
@ -5009,7 +4985,7 @@ export class TeraBlastTypeAttr extends VariableMoveTypeAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (user.isTerastallized()) {
|
||||
if (user.isTerastallized) {
|
||||
moveType.value = user.getTeraType(); // changes move type to tera type
|
||||
return true;
|
||||
}
|
||||
@ -5018,6 +4994,30 @@ export class TeraBlastTypeAttr extends VariableMoveTypeAttr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute used for Tera Starstorm that changes the move type to Stellar
|
||||
* @extends VariableMoveTypeAttr
|
||||
*/
|
||||
export class TeraStarstormTypeAttr extends VariableMoveTypeAttr {
|
||||
/**
|
||||
*
|
||||
* @param user the {@linkcode Pokemon} using the move
|
||||
* @param target n/a
|
||||
* @param move n/a
|
||||
* @param args[0] {@linkcode Utils.NumberHolder} the move type
|
||||
* @returns `true` if the move type is changed to {@linkcode Type.STELLAR}, `false` otherwise
|
||||
*/
|
||||
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (user.isTerastallized && user.hasSpecies(Species.TERAPAGOS)) {
|
||||
const moveType = args[0] as Utils.NumberHolder;
|
||||
|
||||
moveType.value = Type.STELLAR;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class MatchUserTypeAttr extends VariableMoveTypeAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const moveType = args[0];
|
||||
@ -6345,7 +6345,7 @@ export class RemoveTypeAttr extends MoveEffectAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (user.isTerastallized() && user.getTeraType() === this.removedType) { // active tera types cannot be removed
|
||||
if (user.isTerastallized && user.getTeraType() === this.removedType) { // active tera types cannot be removed
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -6525,7 +6525,7 @@ export class ChangeTypeAttr extends MoveEffectAttr {
|
||||
}
|
||||
|
||||
getCondition(): MoveConditionFunc {
|
||||
return (user, target, move) => !target.isTerastallized() && !target.hasAbility(Abilities.MULTITYPE) && !target.hasAbility(Abilities.RKS_SYSTEM) && !(target.getTypes().length === 1 && target.getTypes()[0] === this.type);
|
||||
return (user, target, move) => !target.isTerastallized && !target.hasAbility(Abilities.MULTITYPE) && !target.hasAbility(Abilities.RKS_SYSTEM) && !(target.getTypes().length === 1 && target.getTypes()[0] === this.type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6548,7 +6548,7 @@ export class AddTypeAttr extends MoveEffectAttr {
|
||||
}
|
||||
|
||||
getCondition(): MoveConditionFunc {
|
||||
return (user, target, move) => !target.isTerastallized() && !target.getTypes().includes(this.type);
|
||||
return (user, target, move) => !target.isTerastallized && !target.getTypes().includes(this.type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11076,7 +11076,7 @@ export function initMoves() {
|
||||
.attr(TeraMoveCategoryAttr)
|
||||
.attr(TeraBlastTypeAttr)
|
||||
.attr(TeraBlastPowerAttr)
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, true, { condition: (user, target, move) => user.isTerastallized() && user.isOfType(Type.STELLAR) }),
|
||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1, true, { condition: (user, target, move) => user.isTerastallized && user.isOfType(Type.STELLAR) }),
|
||||
new SelfStatusMove(Moves.SILK_TRAP, Type.BUG, -1, 10, -1, 4, 9)
|
||||
.attr(ProtectAttr, BattlerTagType.SILK_TRAP)
|
||||
.condition(failIfLastCondition),
|
||||
@ -11271,7 +11271,7 @@ export function initMoves() {
|
||||
new AttackMove(Moves.TERA_STARSTORM, Type.NORMAL, MoveCategory.SPECIAL, 120, 100, 5, -1, 0, 9)
|
||||
.attr(TeraMoveCategoryAttr)
|
||||
.attr(TeraStarstormTypeAttr)
|
||||
.attr(VariableTargetAttr, (user, target, move) => (user.hasFusionSpecies(Species.TERAPAGOS) || user.species.speciesId === Species.TERAPAGOS) && user.isTerastallized() ? MoveTarget.ALL_NEAR_ENEMIES : MoveTarget.NEAR_OTHER)
|
||||
.attr(VariableTargetAttr, (user, target, move) => user.hasSpecies(Species.TERAPAGOS) && user.isTerastallized ? MoveTarget.ALL_NEAR_ENEMIES : MoveTarget.NEAR_OTHER)
|
||||
.partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */
|
||||
new AttackMove(Moves.FICKLE_BEAM, Type.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, 30, 0, 9)
|
||||
.attr(PreMoveMessageAttr, doublePowerChanceMessageFunc)
|
||||
|
@ -594,7 +594,7 @@ function doPokemonTradeSequence(tradedPokemon: PlayerPokemon, receivedPokemon: P
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(tradedPokemon.getTeraType()) });
|
||||
sprite.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(tradedPokemon.getTeraType()), isTerastallized: tradedPokemon.isTerastallized });
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", tradedPokemon.getSpriteKey());
|
||||
sprite.setPipelineData("shiny", tradedPokemon.shiny);
|
||||
@ -615,7 +615,7 @@ function doPokemonTradeSequence(tradedPokemon: PlayerPokemon, receivedPokemon: P
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(tradedPokemon.getTeraType()) });
|
||||
sprite.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(tradedPokemon.getTeraType()), isTerastallized: tradedPokemon.isTerastallized });
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", receivedPokemon.getSpriteKey());
|
||||
sprite.setPipelineData("shiny", receivedPokemon.shiny);
|
||||
|
@ -10,7 +10,7 @@ import { HiddenAbilityRateBoosterModifier, IvScannerModifier } from "#app/modifi
|
||||
import type { EnemyPokemon } from "#app/field/pokemon";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import { PlayerGender } from "#enums/player-gender";
|
||||
import { IntegerHolder, randSeedInt } from "#app/utils";
|
||||
import { NumberHolder, randSeedInt } from "#app/utils";
|
||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
|
||||
@ -279,7 +279,7 @@ async function summonSafariPokemon() {
|
||||
if (pokemon.species.abilityHidden) {
|
||||
const hiddenIndex = pokemon.species.ability2 ? 2 : 1;
|
||||
if (pokemon.abilityIndex < hiddenIndex) {
|
||||
const hiddenAbilityChance = new IntegerHolder(256);
|
||||
const hiddenAbilityChance = new NumberHolder(256);
|
||||
globalScene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance);
|
||||
|
||||
const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { generateModifierType, handleMysteryEncounterBattleFailed, initBattleWithEnemyConfig, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { handleMysteryEncounterBattleFailed, initBattleWithEnemyConfig, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { trainerConfigs } from "#app/data/trainer-config";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
@ -23,7 +23,6 @@ import { EggSourceType } from "#enums/egg-source-types";
|
||||
import { EggTier } from "#enums/egg-type";
|
||||
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import type { PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
|
||||
import { modifierTypes } from "#app/modifier/modifier-type";
|
||||
import { Type } from "#enums/type";
|
||||
import { getPokeballTintColor } from "#app/data/pokeball";
|
||||
@ -387,11 +386,7 @@ function getPartyConfig(): EnemyPartyConfig {
|
||||
nature: Nature.ADAMANT,
|
||||
moveSet: [ Moves.METEOR_MASH, Moves.FIRE_PUNCH, Moves.ICE_PUNCH, Moves.THUNDER_PUNCH ],
|
||||
ivs: [ 31, 31, 31, 31, 31, 31 ],
|
||||
modifierConfigs: [
|
||||
{
|
||||
modifier: generateModifierType(modifierTypes.TERA_SHARD, [ Type.STEEL ]) as PokemonHeldItemModifierType,
|
||||
}
|
||||
]
|
||||
tera: Type.STEEL,
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode
|
||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import { PokemonMove } from "#app/field/pokemon";
|
||||
import { IntegerHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils";
|
||||
import { NumberHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils";
|
||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||
import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import type { PokemonHeldItemModifier } from "#app/modifier/modifier";
|
||||
@ -452,7 +452,7 @@ async function postProcessTransformedPokemon(previousPokemon: PlayerPokemon, new
|
||||
if (newPokemon.species.abilityHidden) {
|
||||
const hiddenIndex = newPokemon.species.ability2 ? 2 : 1;
|
||||
if (newPokemon.abilityIndex < hiddenIndex) {
|
||||
const hiddenAbilityChance = new IntegerHolder(256);
|
||||
const hiddenAbilityChance = new NumberHolder(256);
|
||||
globalScene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance);
|
||||
|
||||
const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value);
|
||||
|
@ -46,6 +46,7 @@ import type { Variant } from "#app/data/variant";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonSpecies } from "#app/data/pokemon-species";
|
||||
import { Type } from "#app/enums/type";
|
||||
|
||||
/**
|
||||
* Animates exclamation sprite over trainer's head at start of encounter
|
||||
@ -98,6 +99,7 @@ export interface EnemyPokemonConfig {
|
||||
modifierConfigs?: HeldModifierConfig[];
|
||||
tags?: BattlerTagType[];
|
||||
dataSource?: PokemonData;
|
||||
tera?: Type;
|
||||
aiType?: AiType;
|
||||
}
|
||||
|
||||
@ -329,6 +331,14 @@ export async function initBattleWithEnemyConfig(partyConfig: EnemyPartyConfig):
|
||||
tags.forEach(tag => enemyPokemon.addTag(tag));
|
||||
}
|
||||
|
||||
// Set tera
|
||||
if (config.tera && config.tera !== Type.UNKNOWN) {
|
||||
enemyPokemon.teraType = config.tera;
|
||||
if (battle.trainer) {
|
||||
battle.trainer.config.setInstantTera(e);
|
||||
}
|
||||
}
|
||||
|
||||
// mysteryEncounterBattleEffects will only be used IFF MYSTERY_ENCOUNTER_POST_SUMMON tag is applied
|
||||
if (config.mysteryEncounterBattleEffects) {
|
||||
enemyPokemon.mysteryEncounterBattleEffects = config.mysteryEncounterBattleEffects;
|
||||
|
@ -61,7 +61,7 @@ export function doPokemonTransformationSequence(previousPokemon: PlayerPokemon,
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(previousPokemon.getTeraType()) });
|
||||
sprite.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(previousPokemon.getTeraType()), isTerastallized: previousPokemon.isTerastallized });
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", previousPokemon.getSpriteKey());
|
||||
sprite.setPipelineData("shiny", previousPokemon.shiny);
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { PokemonFormChangeItemModifier, TerastallizeModifier } from "../modifier/modifier";
|
||||
import { PokemonFormChangeItemModifier } from "../modifier/modifier";
|
||||
import type Pokemon from "../field/pokemon";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { MoveCategory, allMoves } from "./move";
|
||||
import { Type } from "#enums/type";
|
||||
import type { Constructor, nil } from "#app/utils";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { Moves } from "#enums/moves";
|
||||
@ -399,23 +398,7 @@ export class SpeciesDefaultFormMatchTrigger extends SpeciesFormChangeTrigger {
|
||||
* @extends SpeciesFormChangeTrigger
|
||||
*/
|
||||
export class SpeciesFormChangeTeraTrigger extends SpeciesFormChangeTrigger {
|
||||
/** The Tera type that triggers the form change */
|
||||
private teraType: Type;
|
||||
|
||||
constructor(teraType: Type) {
|
||||
super();
|
||||
this.teraType = teraType;
|
||||
this.description = i18next.t("pokemonEvolutions:Forms.tera", { teraType: i18next.t(`pokemonInfo:Type.${Type[this.teraType]}`) });
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the associated Pokémon has the required Tera Shard that matches with the associated Tera type.
|
||||
* @param {Pokemon} pokemon the Pokémon that is trying to do the form change
|
||||
* @returns `true` if the Pokémon can change forms, `false` otherwise
|
||||
*/
|
||||
canChange(pokemon: Pokemon): boolean {
|
||||
return !!globalScene.findModifier(m => m instanceof TerastallizeModifier && m.pokemonId === pokemon.id && m.teraType === this.teraType);
|
||||
}
|
||||
description = i18next.t("pokemonEvolutions:Forms.tera" );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -425,10 +408,6 @@ export class SpeciesFormChangeTeraTrigger extends SpeciesFormChangeTrigger {
|
||||
*/
|
||||
export class SpeciesFormChangeLapseTeraTrigger extends SpeciesFormChangeTrigger {
|
||||
description = i18next.t("pokemonEvolutions:Forms.teraLapse");
|
||||
|
||||
canChange(pokemon: Pokemon): boolean {
|
||||
return !!globalScene.findModifier(m => m instanceof TerastallizeModifier && m.pokemonId === pokemon.id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -992,19 +971,19 @@ export const pokemonFormChanges: PokemonFormChanges = {
|
||||
new SpeciesFormChange(Species.OGERPON, "teal-mask", "wellspring-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.WELLSPRING_MASK)),
|
||||
new SpeciesFormChange(Species.OGERPON, "teal-mask", "hearthflame-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.HEARTHFLAME_MASK)),
|
||||
new SpeciesFormChange(Species.OGERPON, "teal-mask", "cornerstone-mask", new SpeciesFormChangeItemTrigger(FormChangeItem.CORNERSTONE_MASK)),
|
||||
new SpeciesFormChange(Species.OGERPON, "teal-mask", "teal-mask-tera", new SpeciesFormChangeTeraTrigger(Type.GRASS)),
|
||||
new SpeciesFormChange(Species.OGERPON, "teal-mask-tera", "teal-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.GRASS)),
|
||||
new SpeciesFormChange(Species.OGERPON, "wellspring-mask", "wellspring-mask-tera", new SpeciesFormChangeTeraTrigger(Type.WATER)),
|
||||
new SpeciesFormChange(Species.OGERPON, "wellspring-mask-tera", "wellspring-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.WATER)),
|
||||
new SpeciesFormChange(Species.OGERPON, "hearthflame-mask", "hearthflame-mask-tera", new SpeciesFormChangeTeraTrigger(Type.FIRE)),
|
||||
new SpeciesFormChange(Species.OGERPON, "hearthflame-mask-tera", "hearthflame-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.FIRE)),
|
||||
new SpeciesFormChange(Species.OGERPON, "cornerstone-mask", "cornerstone-mask-tera", new SpeciesFormChangeTeraTrigger(Type.ROCK)),
|
||||
new SpeciesFormChange(Species.OGERPON, "cornerstone-mask-tera", "cornerstone-mask", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.ROCK))
|
||||
new SpeciesFormChange(Species.OGERPON, "teal-mask", "teal-mask-tera", new SpeciesFormChangeTeraTrigger(), true),
|
||||
new SpeciesFormChange(Species.OGERPON, "teal-mask-tera", "teal-mask", new SpeciesFormChangeLapseTeraTrigger(), true),
|
||||
new SpeciesFormChange(Species.OGERPON, "wellspring-mask", "wellspring-mask-tera", new SpeciesFormChangeTeraTrigger(), true),
|
||||
new SpeciesFormChange(Species.OGERPON, "wellspring-mask-tera", "wellspring-mask", new SpeciesFormChangeLapseTeraTrigger(), true),
|
||||
new SpeciesFormChange(Species.OGERPON, "hearthflame-mask", "hearthflame-mask-tera", new SpeciesFormChangeTeraTrigger(), true),
|
||||
new SpeciesFormChange(Species.OGERPON, "hearthflame-mask-tera", "hearthflame-mask", new SpeciesFormChangeLapseTeraTrigger(), true),
|
||||
new SpeciesFormChange(Species.OGERPON, "cornerstone-mask", "cornerstone-mask-tera", new SpeciesFormChangeTeraTrigger(), true),
|
||||
new SpeciesFormChange(Species.OGERPON, "cornerstone-mask-tera", "cornerstone-mask", new SpeciesFormChangeLapseTeraTrigger(), true)
|
||||
],
|
||||
[Species.TERAPAGOS]: [
|
||||
new SpeciesFormChange(Species.TERAPAGOS, "", "terastal", new SpeciesFormChangeAbilityTrigger(), true),
|
||||
new SpeciesFormChange(Species.TERAPAGOS, "terastal", "stellar", new SpeciesFormChangeTeraTrigger(Type.STELLAR)),
|
||||
new SpeciesFormChange(Species.TERAPAGOS, "stellar", "terastal", new SpeciesFormChangeLapseTeraTrigger(), true, new SpeciesFormChangeCondition(p => p.getTeraType() !== Type.STELLAR))
|
||||
new SpeciesFormChange(Species.TERAPAGOS, "terastal", "stellar", new SpeciesFormChangeTeraTrigger(), true),
|
||||
new SpeciesFormChange(Species.TERAPAGOS, "stellar", "terastal", new SpeciesFormChangeLapseTeraTrigger(), true)
|
||||
],
|
||||
[Species.GALAR_DARMANITAN]: [
|
||||
new SpeciesFormChange(Species.GALAR_DARMANITAN, "", "zen", new SpeciesFormChangeAbilityTrigger(), true),
|
||||
|
@ -7,7 +7,7 @@ import i18next from "i18next";
|
||||
import type { AnySound } from "#app/battle-scene";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { GameMode } from "#app/game-mode";
|
||||
import type { StarterMoveset } from "#app/system/game-data";
|
||||
import { DexAttr, type StarterMoveset } from "#app/system/game-data";
|
||||
import * as Utils from "#app/utils";
|
||||
import { uncatchableSpecies } from "#app/data/balance/biomes";
|
||||
import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||
@ -32,6 +32,37 @@ export enum Region {
|
||||
PALDEA
|
||||
}
|
||||
|
||||
// TODO: this is horrible and will need to be removed once a refactor/cleanup of forms is executed.
|
||||
export const normalForm: Species[] = [
|
||||
Species.PIKACHU,
|
||||
Species.RAICHU,
|
||||
Species.EEVEE,
|
||||
Species.JOLTEON,
|
||||
Species.FLAREON,
|
||||
Species.VAPOREON,
|
||||
Species.ESPEON,
|
||||
Species.UMBREON,
|
||||
Species.LEAFEON,
|
||||
Species.GLACEON,
|
||||
Species.SYLVEON,
|
||||
Species.PICHU,
|
||||
Species.ROTOM,
|
||||
Species.DIALGA,
|
||||
Species.PALKIA,
|
||||
Species.KYUREM,
|
||||
Species.GENESECT,
|
||||
Species.FROAKIE,
|
||||
Species.FROGADIER,
|
||||
Species.GRENINJA,
|
||||
Species.ROCKRUFF,
|
||||
Species.NECROZMA,
|
||||
Species.MAGEARNA,
|
||||
Species.MARSHADOW,
|
||||
Species.CRAMORANT,
|
||||
Species.ZARUDE,
|
||||
Species.CALYREX
|
||||
];
|
||||
|
||||
/**
|
||||
* Gets the {@linkcode PokemonSpecies} object associated with the {@linkcode Species} enum given
|
||||
* @param species The species to fetch
|
||||
@ -997,25 +1028,59 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
||||
? this.forms[formIndex || 0].getFormSpriteKey()
|
||||
: "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a {@linkcode bigint} corresponding to the maximum unlocks possible for this species,
|
||||
* taking into account if the species has a male/female gender, and which variants are implemented.
|
||||
* @returns {@linkcode bigint} Maximum unlocks, can be compared with {@linkcode DexEntry.caughtAttr}.
|
||||
*/
|
||||
getFullUnlocksData(): bigint {
|
||||
let caughtAttr: bigint = 0n;
|
||||
caughtAttr += DexAttr.NON_SHINY;
|
||||
caughtAttr += DexAttr.SHINY;
|
||||
if (this.malePercent !== null) {
|
||||
if (this.malePercent > 0) {
|
||||
caughtAttr += DexAttr.MALE;
|
||||
}
|
||||
if (this.malePercent < 100) {
|
||||
caughtAttr += DexAttr.FEMALE;
|
||||
}
|
||||
}
|
||||
caughtAttr += DexAttr.DEFAULT_VARIANT;
|
||||
if (this.hasVariants()) {
|
||||
caughtAttr += DexAttr.VARIANT_2;
|
||||
caughtAttr += DexAttr.VARIANT_3;
|
||||
}
|
||||
|
||||
// Summing successive bigints for each obtainable form
|
||||
caughtAttr += this?.forms?.length > 1 ?
|
||||
this.forms.map((f, index) => f.isUnobtainable ? 0n : 128n * 2n ** BigInt(index)).reduce((acc, val) => acc + val, 0n) :
|
||||
DexAttr.DEFAULT_FORM;
|
||||
|
||||
return caughtAttr;
|
||||
}
|
||||
}
|
||||
|
||||
export class PokemonForm extends PokemonSpeciesForm {
|
||||
public formName: string;
|
||||
public formKey: string;
|
||||
public formSpriteKey: string | null;
|
||||
public isUnobtainable: boolean;
|
||||
|
||||
// This is a collection of form keys that have in-run form changes, but should still be separately selectable from the start screen
|
||||
private starterSelectableKeys: string[] = [ "10", "50", "10-pc", "50-pc", "red", "orange", "yellow", "green", "blue", "indigo", "violet" ];
|
||||
|
||||
constructor(formName: string, formKey: string, type1: Type, type2: Type | null, height: number, weight: number, ability1: Abilities, ability2: Abilities, abilityHidden: Abilities,
|
||||
baseTotal: number, baseHp: number, baseAtk: number, baseDef: number, baseSpatk: number, baseSpdef: number, baseSpd: number,
|
||||
catchRate: number, baseFriendship: number, baseExp: number, genderDiffs: boolean = false, formSpriteKey: string | null = null, isStarterSelectable: boolean = false
|
||||
catchRate: number, baseFriendship: number, baseExp: number, genderDiffs: boolean = false, formSpriteKey: string | null = null, isStarterSelectable: boolean = false,
|
||||
isUnobtainable: boolean = false
|
||||
) {
|
||||
super(type1, type2, height, weight, ability1, ability2, abilityHidden, baseTotal, baseHp, baseAtk, baseDef, baseSpatk, baseSpdef, baseSpd,
|
||||
catchRate, baseFriendship, baseExp, genderDiffs, (isStarterSelectable || !formKey));
|
||||
this.formName = formName;
|
||||
this.formKey = formKey;
|
||||
this.formSpriteKey = formSpriteKey;
|
||||
this.isUnobtainable = isUnobtainable;
|
||||
}
|
||||
|
||||
getFormSpriteKey(_formIndex?: number) {
|
||||
@ -1812,7 +1877,7 @@ export function initSpecies() {
|
||||
new PokemonForm("Dragon", "dragon", Type.DRAGON, null, 3.2, 320, Abilities.MULTITYPE, Abilities.NONE, Abilities.NONE, 720, 120, 120, 120, 120, 120, 120, 3, 0, 360),
|
||||
new PokemonForm("Dark", "dark", Type.DARK, null, 3.2, 320, Abilities.MULTITYPE, Abilities.NONE, Abilities.NONE, 720, 120, 120, 120, 120, 120, 120, 3, 0, 360),
|
||||
new PokemonForm("Fairy", "fairy", Type.FAIRY, null, 3.2, 320, Abilities.MULTITYPE, Abilities.NONE, Abilities.NONE, 720, 120, 120, 120, 120, 120, 120, 3, 0, 360),
|
||||
new PokemonForm("???", "unknown", Type.UNKNOWN, null, 3.2, 320, Abilities.MULTITYPE, Abilities.NONE, Abilities.NONE, 720, 120, 120, 120, 120, 120, 120, 3, 0, 360),
|
||||
new PokemonForm("???", "unknown", Type.UNKNOWN, null, 3.2, 320, Abilities.MULTITYPE, Abilities.NONE, Abilities.NONE, 720, 120, 120, 120, 120, 120, 120, 3, 0, 360, false, null, false, true),
|
||||
),
|
||||
new PokemonSpecies(Species.VICTINI, 5, false, false, true, "Victory Pokémon", Type.PSYCHIC, Type.FIRE, 0.4, 4, Abilities.VICTORY_STAR, Abilities.NONE, Abilities.NONE, 600, 100, 100, 100, 100, 100, 100, 3, 100, 300, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(Species.SNIVY, 5, false, false, false, "Grass Snake Pokémon", Type.GRASS, null, 0.6, 8.1, Abilities.OVERGROW, Abilities.NONE, Abilities.CONTRARY, 308, 45, 45, 55, 45, 55, 63, 45, 70, 62, GrowthRate.MEDIUM_SLOW, 87.5, false),
|
||||
@ -2366,7 +2431,7 @@ export function initSpecies() {
|
||||
),
|
||||
new PokemonSpecies(Species.MARSHADOW, 7, false, false, true, "Gloomdweller Pokémon", Type.FIGHTING, Type.GHOST, 0.7, 22.2, Abilities.TECHNICIAN, Abilities.NONE, Abilities.NONE, 600, 90, 125, 80, 90, 90, 125, 3, 0, 300, GrowthRate.SLOW, null, false, true,
|
||||
new PokemonForm("Normal", "", Type.FIGHTING, Type.GHOST, 0.7, 22.2, Abilities.TECHNICIAN, Abilities.NONE, Abilities.NONE, 600, 90, 125, 80, 90, 90, 125, 3, 0, 300, false, null, true),
|
||||
new PokemonForm("Zenith", "zenith", Type.FIGHTING, Type.GHOST, 0.7, 22.2, Abilities.TECHNICIAN, Abilities.NONE, Abilities.NONE, 600, 90, 125, 80, 90, 90, 125, 3, 0, 300)
|
||||
new PokemonForm("Zenith", "zenith", Type.FIGHTING, Type.GHOST, 0.7, 22.2, Abilities.TECHNICIAN, Abilities.NONE, Abilities.NONE, 600, 90, 125, 80, 90, 90, 125, 3, 0, 300, false, null, false, true)
|
||||
),
|
||||
new PokemonSpecies(Species.POIPOLE, 7, true, false, false, "Poison Pin Pokémon", Type.POISON, null, 0.6, 1.8, Abilities.BEAST_BOOST, Abilities.NONE, Abilities.NONE, 420, 67, 73, 67, 73, 67, 73, 45, 0, 210, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(Species.NAGANADEL, 7, true, false, false, "Poison Pin Pokémon", Type.POISON, Type.DRAGON, 3.6, 150, Abilities.BEAST_BOOST, Abilities.NONE, Abilities.NONE, 540, 73, 73, 73, 127, 73, 121, 45, 0, 270, GrowthRate.SLOW, null, false),
|
||||
@ -2465,11 +2530,11 @@ export function initSpecies() {
|
||||
new PokemonSpecies(Species.GRAPPLOCT, 8, false, false, false, "Jujitsu Pokémon", Type.FIGHTING, null, 1.6, 39, Abilities.LIMBER, Abilities.NONE, Abilities.TECHNICIAN, 480, 80, 118, 90, 70, 80, 42, 45, 50, 168, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||
new PokemonSpecies(Species.SINISTEA, 8, false, false, false, "Black Tea Pokémon", Type.GHOST, null, 0.1, 0.2, Abilities.WEAK_ARMOR, Abilities.NONE, Abilities.CURSED_BODY, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, GrowthRate.MEDIUM_FAST, null, false, false,
|
||||
new PokemonForm("Phony Form", "phony", Type.GHOST, null, 0.1, 0.2, Abilities.WEAK_ARMOR, Abilities.NONE, Abilities.CURSED_BODY, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, "", true),
|
||||
new PokemonForm("Antique Form", "antique", Type.GHOST, null, 0.1, 0.2, Abilities.WEAK_ARMOR, Abilities.NONE, Abilities.CURSED_BODY, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, "", true),
|
||||
new PokemonForm("Antique Form", "antique", Type.GHOST, null, 0.1, 0.2, Abilities.WEAK_ARMOR, Abilities.NONE, Abilities.CURSED_BODY, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, "", true, true),
|
||||
),
|
||||
new PokemonSpecies(Species.POLTEAGEIST, 8, false, false, false, "Black Tea Pokémon", Type.GHOST, null, 0.2, 0.4, Abilities.WEAK_ARMOR, Abilities.NONE, Abilities.CURSED_BODY, 508, 60, 65, 65, 134, 114, 70, 60, 50, 178, GrowthRate.MEDIUM_FAST, null, false, false,
|
||||
new PokemonForm("Phony Form", "phony", Type.GHOST, null, 0.2, 0.4, Abilities.WEAK_ARMOR, Abilities.NONE, Abilities.CURSED_BODY, 508, 60, 65, 65, 134, 114, 70, 60, 50, 178, false, "", true),
|
||||
new PokemonForm("Antique Form", "antique", Type.GHOST, null, 0.2, 0.4, Abilities.WEAK_ARMOR, Abilities.NONE, Abilities.CURSED_BODY, 508, 60, 65, 65, 134, 114, 70, 60, 50, 178, false, "", true),
|
||||
new PokemonForm("Antique Form", "antique", Type.GHOST, null, 0.2, 0.4, Abilities.WEAK_ARMOR, Abilities.NONE, Abilities.CURSED_BODY, 508, 60, 65, 65, 134, 114, 70, 60, 50, 178, false, "", true, true),
|
||||
),
|
||||
new PokemonSpecies(Species.HATENNA, 8, false, false, false, "Calm Pokémon", Type.PSYCHIC, null, 0.4, 3.4, Abilities.HEALER, Abilities.ANTICIPATION, Abilities.MAGIC_BOUNCE, 265, 42, 30, 45, 56, 53, 39, 235, 50, 53, GrowthRate.SLOW, 0, false),
|
||||
new PokemonSpecies(Species.HATTREM, 8, false, false, false, "Serene Pokémon", Type.PSYCHIC, null, 0.6, 4.8, Abilities.HEALER, Abilities.ANTICIPATION, Abilities.MAGIC_BOUNCE, 370, 57, 40, 65, 86, 73, 49, 120, 50, 130, GrowthRate.SLOW, 0, false),
|
||||
|
@ -175,11 +175,51 @@ export const trainerPartyTemplates = {
|
||||
type PartyTemplateFunc = () => TrainerPartyTemplate;
|
||||
type PartyMemberFunc = (level: number, strength: PartyMemberStrength) => EnemyPokemon;
|
||||
type GenModifiersFunc = (party: EnemyPokemon[]) => PersistentModifier[];
|
||||
type GenAIFunc = (party: EnemyPokemon[]) => void;
|
||||
|
||||
export interface PartyMemberFuncs {
|
||||
[key: number]: PartyMemberFunc
|
||||
}
|
||||
|
||||
export enum TeraAIMode {
|
||||
NO_TERA,
|
||||
INSTANT_TERA,
|
||||
SMART_TERA
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores data and helper functions about a trainers AI options.
|
||||
*/
|
||||
export class TrainerAI {
|
||||
public teraMode: TeraAIMode = TeraAIMode.NO_TERA;
|
||||
public instantTeras: number[];
|
||||
|
||||
/**
|
||||
* @param canTerastallize Whether this trainer is allowed to tera
|
||||
*/
|
||||
constructor(teraMode: TeraAIMode = TeraAIMode.NO_TERA) {
|
||||
this.teraMode = teraMode;
|
||||
this.instantTeras = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a trainer can tera
|
||||
* @returns Whether this trainer can currently tera
|
||||
*/
|
||||
public canTerastallize() {
|
||||
return this.teraMode !== TeraAIMode.NO_TERA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a pokemon on this AI to just instantly tera on first move used
|
||||
* @param index The index of the pokemon to instantly tera
|
||||
*/
|
||||
public setInstantTera(index: number) {
|
||||
this.teraMode = TeraAIMode.INSTANT_TERA;
|
||||
this.instantTeras.push(index);
|
||||
}
|
||||
}
|
||||
|
||||
export class TrainerConfig {
|
||||
public trainerType: TrainerType;
|
||||
public trainerTypeDouble: TrainerType;
|
||||
@ -203,6 +243,7 @@ export class TrainerConfig {
|
||||
public doubleEncounterBgm: string;
|
||||
public victoryBgm: string;
|
||||
public genModifiersFunc: GenModifiersFunc;
|
||||
public genAIFuncs: GenAIFunc[] = [];
|
||||
public modifierRewardFuncs: ModifierTypeFunc[] = [];
|
||||
public partyTemplates: TrainerPartyTemplate[];
|
||||
public partyTemplateFunc: PartyTemplateFunc;
|
||||
@ -212,6 +253,7 @@ export class TrainerConfig {
|
||||
public speciesFilter: PokemonSpeciesFilter;
|
||||
public specialtyTypes: Type[] = [];
|
||||
public hasVoucher: boolean = false;
|
||||
public trainerAI: TrainerAI;
|
||||
|
||||
public encounterMessages: string[] = [];
|
||||
public victoryMessages: string[] = [];
|
||||
@ -227,6 +269,7 @@ export class TrainerConfig {
|
||||
|
||||
constructor(trainerType: TrainerType, allowLegendaries?: boolean) {
|
||||
this.trainerType = trainerType;
|
||||
this.trainerAI = new TrainerAI();
|
||||
this.name = Utils.toReadableString(TrainerType[this.getDerivedType()]);
|
||||
this.battleBgm = "battle_trainer";
|
||||
this.mixedBattleBgm = "battle_trainer";
|
||||
@ -550,6 +593,47 @@ export class TrainerConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets random pokemon from the trainers team to instant tera. Uses their specialty types is they have one.
|
||||
* @param count The amount of pokemon to have instant tera
|
||||
* @returns this
|
||||
*/
|
||||
setRandomTeraModifiers(count: () => integer): TrainerConfig {
|
||||
this.genAIFuncs.push((party: EnemyPokemon[]) => {
|
||||
const partyMemberIndexes = new Array(party.length).fill(null).map((_, i) => i);
|
||||
for (let t = 0; t < Math.min(count(), party.length); t++) {
|
||||
const randomIndex = Utils.randSeedItem(partyMemberIndexes);
|
||||
partyMemberIndexes.splice(partyMemberIndexes.indexOf(randomIndex), 1);
|
||||
if (this.specialtyTypes?.length) {
|
||||
party[randomIndex].teraType = Utils.randSeedItem(this.specialtyTypes);
|
||||
}
|
||||
this.trainerAI.setInstantTera(randomIndex);
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a specific pokemon to instant tera
|
||||
* @param index The index within the team to have instant tera
|
||||
* @returns this
|
||||
*/
|
||||
setInstantTera(index: number): TrainerConfig {
|
||||
this.trainerAI.setInstantTera(index);
|
||||
return this;
|
||||
}
|
||||
|
||||
// function getRandomTeraModifiers(party: EnemyPokemon[], count: integer, types?: Type[]): PersistentModifier[] {
|
||||
// const ret: PersistentModifier[] = [];
|
||||
// const partyMemberIndexes = new Array(party.length).fill(null).map((_, i) => i);
|
||||
// for (let t = 0; t < Math.min(count, party.length); t++) {
|
||||
// const randomIndex = Utils.randSeedItem(partyMemberIndexes);
|
||||
// partyMemberIndexes.splice(partyMemberIndexes.indexOf(randomIndex), 1);
|
||||
// ret.push(modifierTypes.TERA_SHARD().generateType([], [ Utils.randSeedItem(types ? types : party[randomIndex].getTypes()) ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); // TODO: is the bang correct?
|
||||
// }
|
||||
// return ret;
|
||||
// }
|
||||
|
||||
setEventModifierRewardFuncs(...modifierTypeFuncs: (() => ModifierTypeFunc)[]): TrainerConfig {
|
||||
this.eventRewardFuncs = modifierTypeFuncs.map(func => () => {
|
||||
const modifierTypeFunc = func();
|
||||
@ -581,107 +665,107 @@ export class TrainerConfig {
|
||||
switch (team) {
|
||||
case "rocket": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.RATTATA, Species.KOFFING, Species.EKANS, Species.ZUBAT, Species.MAGIKARP, Species.HOUNDOUR, Species.ONIX, Species.CUBONE, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB, Species.DROWZEE, Species.VILEPLUME ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.PORYGON, Species.MANKEY, Species.MAGNEMITE, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE, Species.PALDEA_TAUROS, Species.OMANYTE, Species.KABUTO, Species.MAGBY, Species.ELEKID ],
|
||||
[TrainerPoolTier.RARE]: [ Species.DRATINI, Species.LARVITAR ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.RATICATE, Species.ARBOK, Species.VILEPLUME, Species.ARCANINE, Species.GENGAR, Species.HYPNO, Species.ELECTRODE, Species.EXEGGUTOR, Species.CUBONE, Species.KOFFING, Species.GYARADOS, Species.CROBAT, Species.STEELIX, Species.HOUNDOOM, Species.HONCHKROW ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.OMASTAR, Species.KABUTOPS, Species.MAGNEZONE, Species.ELECTIVIRE, Species.MAGMORTAR, Species.PORYGON_Z, Species.ANNIHILAPE, Species.ALOLA_SANDSLASH, Species.ALOLA_PERSIAN, Species.ALOLA_GOLEM, Species.ALOLA_MUK, Species.PALDEA_TAUROS ],
|
||||
[TrainerPoolTier.RARE]: [ Species.DRAGONITE, Species.TYRANITAR ]
|
||||
};
|
||||
}
|
||||
case "magma": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.SLUGMA, Species.SOLROCK, Species.HIPPOPOTAS, Species.BALTOY, Species.ROLYCOLY, Species.GLIGAR, Species.TORKOAL, Species.HOUNDOUR, Species.MAGBY ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.TRAPINCH, Species.SILICOBRA, Species.RHYHORN, Species.ANORITH, Species.LILEEP, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON, Species.TOEDSCOOL ],
|
||||
[TrainerPoolTier.RARE]: [ Species.CAPSAKID, Species.CHARCADET ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.ARCANINE, Species.MAGCARGO, Species.HOUNDOOM, Species.TORKOAL, Species.SOLROCK, Species.CLAYDOL, Species.HIPPOWDON, Species.MAGMORTAR, Species.GLISCOR, Species.COALOSSAL ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.AGGRON, Species.FLYGON, Species.CRADILY, Species.ARMALDO, Species.RHYPERIOR, Species.TURTONATOR, Species.SANDACONDA, Species.TOEDSCRUEL, Species.HISUI_ARCANINE ],
|
||||
[TrainerPoolTier.RARE]: [ Species.CHARCADET, Species.SCOVILLAIN ]
|
||||
};
|
||||
}
|
||||
case "aqua": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.CORPHISH, Species.SPHEAL, Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.AZURILL, Species.LOTAD, Species.WAILMER, Species.REMORAID, Species.BARBOACH ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.MANTYKE, Species.HISUI_QWILFISH, Species.ARROKUDA, Species.DHELMISE, Species.CLOBBOPUS, Species.FEEBAS, Species.PALDEA_WOOPER, Species.HORSEA, Species.SKRELP ],
|
||||
[TrainerPoolTier.RARE]: [ Species.DONDOZO, Species.BASCULEGION ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.TENTACRUEL, Species.LANTURN, Species.AZUMARILL, Species.QUAGSIRE, Species.OCTILLERY, Species.LUDICOLO, Species.PELIPPER, Species.WAILORD, Species.WHISCASH, Species.CRAWDAUNT, Species.WALREIN, Species.CLAMPERL ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.QUAGSIRE, Species.MANTINE, Species.KINGDRA, Species.MILOTIC, Species.DRAGALGE, Species.DHELMISE, Species.BARRASKEWDA, Species.GRAPPLOCT, Species.OVERQWIL ],
|
||||
[TrainerPoolTier.RARE]: [ Species.BASCULEGION, Species.DONDOZO ]
|
||||
};
|
||||
}
|
||||
case "galactic": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.BRONZOR, Species.SWINUB, Species.YANMA, Species.LICKITUNG, Species.TANGELA, Species.MAGBY, Species.ELEKID, Species.SKORUPI, Species.ZUBAT, Species.MURKROW, Species.MAGIKARP, Species.VOLTORB ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.SNEASEL, Species.DUSKULL, Species.ROTOM, Species.HISUI_VOLTORB, Species.GLIGAR, Species.ABRA ],
|
||||
[TrainerPoolTier.RARE]: [ Species.URSALUNA, Species.HISUI_LILLIGANT, Species.SPIRITOMB, Species.HISUI_SNEASEL ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.ELECTRODE, Species.GYARADOS, Species.CROBAT, Species.HONCHKROW, Species.BRONZONG, Species.DRAPION, Species.LICKILICKY, Species.TANGROWTH, Species.ELECTIVIRE, Species.MAGMORTAR, Species.YANMEGA, Species.MAMOSWINE ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.ALAKAZAM, Species.WEAVILE, Species.GLISCOR, Species.DUSKNOIR, Species.ROTOM, Species.OVERQWIL, Species.HISUI_ARCANINE, Species.HISUI_ELECTRODE ],
|
||||
[TrainerPoolTier.RARE]: [ Species.SPIRITOMB, Species.URSALUNA, Species.SNEASLER, Species.HISUI_LILLIGANT ]
|
||||
};
|
||||
}
|
||||
case "plasma": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.YAMASK, Species.ROGGENROLA, Species.JOLTIK, Species.TYMPOLE, Species.FRILLISH, Species.FERROSEED, Species.SANDILE, Species.TIMBURR, Species.DARUMAKA, Species.FOONGUS, Species.CUBCHOO, Species.VANILLITE ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.PAWNIARD, Species.VULLABY, Species.ZORUA, Species.DRILBUR, Species.KLINK, Species.TYNAMO, Species.GALAR_DARUMAKA, Species.GOLETT, Species.MIENFOO, Species.DURANT, Species.SIGILYPH ],
|
||||
[TrainerPoolTier.RARE]: [ Species.HISUI_ZORUA, Species.AXEW, Species.DEINO, Species.HISUI_BRAVIARY ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.GIGALITH, Species.CONKELDURR, Species.SEISMITOAD, Species.KROOKODILE, Species.DARMANITAN, Species.COFAGRIGUS, Species.VANILLUXE, Species.AMOONGUSS, Species.JELLICENT, Species.GALVANTULA, Species.FERROTHORN, Species.BEARTIC ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.EXCADRILL, Species.SIGILYPH, Species.ZOROARK, Species.KLINKLANG, Species.EELEKTROSS, Species.MIENSHAO, Species.GOLURK, Species.BISHARP, Species.MANDIBUZZ, Species.DURANT, Species.GALAR_DARMANITAN ],
|
||||
[TrainerPoolTier.RARE]: [ Species.HAXORUS, Species.HYDREIGON, Species.HISUI_ZOROARK, Species.HISUI_BRAVIARY ]
|
||||
};
|
||||
}
|
||||
case "plasma_2": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.MAGNEMITE, Species.GRIMER, Species.VOLTORB, Species.PORYGON, Species.BRONZOR, Species.MUNNA, Species.SOLOSIS, Species.JOLTIK, Species.FERROSEED, Species.TYNAMO, Species.ELGYEM ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.BELDUM, Species.ROTOM, Species.TIRTOUGA, Species.ARCHEN, Species.GOLETT, Species.DURANT, Species.GRUBBIN, Species.BLIPBUG, Species.VAROOM, Species.ALOLA_GRIMER, Species.HISUI_VOLTORB ],
|
||||
[TrainerPoolTier.RARE]: [ Species.ELEKID, Species.MAGBY, Species.PAWNIARD, Species.DURALUDON ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.MUK, Species.ELECTRODE, Species.BRONZONG, Species.MAGNEZONE, Species.PORYGON_Z, Species.MUSHARNA, Species.REUNICLUS, Species.GALVANTULA, Species.FERROTHORN, Species.EELEKTROSS, Species.BEHEEYEM ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.METAGROSS, Species.ROTOM, Species.CARRACOSTA, Species.ARCHEOPS, Species.GOLURK, Species.DURANT, Species.VIKAVOLT, Species.ORBEETLE, Species.REVAVROOM, Species.ALOLA_MUK, Species.HISUI_ELECTRODE ],
|
||||
[TrainerPoolTier.RARE]: [ Species.ELECTIVIRE, Species.MAGMORTAR, Species.BISHARP, Species.ARCHALUDON ]
|
||||
};
|
||||
}
|
||||
case "flare": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.INKAY, Species.FOONGUS, Species.HELIOPTILE, Species.ELECTRIKE, Species.SKORUPI, Species.PURRLOIN, Species.CLAWITZER, Species.PANCHAM, Species.ESPURR, Species.BUNNELBY ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.LITWICK, Species.SNEASEL, Species.PUMPKABOO, Species.PHANTUMP, Species.HONEDGE, Species.BINACLE, Species.HOUNDOUR, Species.SKRELP, Species.SLIGGOO ],
|
||||
[TrainerPoolTier.RARE]: [ Species.NOIBAT, Species.HISUI_AVALUGG, Species.HISUI_SLIGGOO ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.MANECTRIC, Species.DRAPION, Species.LIEPARD, Species.AMOONGUSS, Species.DIGGERSBY, Species.TALONFLAME, Species.PYROAR, Species.PANGORO, Species.MEOWSTIC, Species.MALAMAR, Species.CLAWITZER, Species.HELIOLISK ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.HOUNDOOM, Species.WEAVILE, Species.CHANDELURE, Species.AEGISLASH, Species.BARBARACLE, Species.DRAGALGE, Species.GOODRA, Species.TREVENANT, Species.GOURGEIST ],
|
||||
[TrainerPoolTier.RARE]: [ Species.NOIVERN, Species.HISUI_GOODRA, Species.HISUI_AVALUGG ]
|
||||
};
|
||||
}
|
||||
case "aether": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.BRUXISH, Species.SLOWPOKE, Species.BALTOY, Species.EXEGGCUTE, Species.ABRA, Species.ALOLA_RAICHU, Species.ELGYEM, Species.NATU, Species.BLIPBUG, Species.GIRAFARIG, Species.ORANGURU ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.GALAR_SLOWPOKE, Species.MEDITITE, Species.BELDUM, Species.HATENNA, Species.INKAY, Species.RALTS, Species.GALAR_MR_MIME ],
|
||||
[TrainerPoolTier.RARE]: [ Species.ARMAROUGE, Species.HISUI_BRAVIARY, Species.PORYGON ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.ALAKAZAM, Species.SLOWBRO, Species.EXEGGUTOR, Species.XATU, Species.CLAYDOL, Species.BEHEEYEM, Species.ORANGURU, Species.BRUXISH, Species.ORBEETLE, Species.FARIGIRAF, Species.ALOLA_RAICHU ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.KIRLIA, Species.MEDICHAM, Species.METAGROSS, Species.MALAMAR, Species.HATTERENE, Species.MR_RIME, Species.GALAR_SLOWKING ],
|
||||
[TrainerPoolTier.RARE]: [ Species.PORYGON_Z, Species.ARMAROUGE, Species.HISUI_BRAVIARY ]
|
||||
};
|
||||
}
|
||||
case "skull": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.MAREANIE, Species.ALOLA_GRIMER, Species.GASTLY, Species.ZUBAT, Species.FOMANTIS, Species.VENIPEDE, Species.BUDEW, Species.KOFFING, Species.STUNKY, Species.CROAGUNK, Species.NIDORAN_F ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.GALAR_SLOWPOKE, Species.SKORUPI, Species.PALDEA_WOOPER, Species.VULLABY, Species.HISUI_QWILFISH, Species.GLIMMET ],
|
||||
[TrainerPoolTier.RARE]: [ Species.SKRELP, Species.HISUI_SNEASEL ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.NIDOQUEEN, Species.GENGAR, Species.KOFFING, Species.CROBAT, Species.ROSERADE, Species.SKUNTANK, Species.TOXICROAK, Species.SCOLIPEDE, Species.TOXAPEX, Species.LURANTIS, Species.ALOLA_MUK ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.DRAPION, Species.MANDIBUZZ, Species.OVERQWIL, Species.GLIMMORA, Species.CLODSIRE, Species.GALAR_SLOWBRO ],
|
||||
[TrainerPoolTier.RARE]: [ Species.DRAGALGE, Species.SNEASLER ]
|
||||
};
|
||||
}
|
||||
case "macro": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.HATENNA, Species.FEEBAS, Species.BOUNSWEET, Species.SALANDIT, Species.GALAR_PONYTA, Species.GOTHITA, Species.FROSLASS, Species.VULPIX, Species.FRILLISH, Species.ODDISH, Species.SINISTEA ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.VULLABY, Species.MAREANIE, Species.ALOLA_VULPIX, Species.TOGEPI, Species.GALAR_CORSOLA, Species.APPLIN ],
|
||||
[TrainerPoolTier.RARE]: [ Species.TINKATINK, Species.HISUI_LILLIGANT ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.NINETALES, Species.BELLOSSOM, Species.MILOTIC, Species.FROSLASS, Species.GOTHITELLE, Species.JELLICENT, Species.SALAZZLE, Species.TSAREENA, Species.POLTEAGEIST, Species.HATTERENE, Species.GALAR_RAPIDASH ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.TOGEKISS, Species.MANDIBUZZ, Species.TOXAPEX, Species.APPLETUN, Species.CURSOLA, Species.ALOLA_NINETALES ],
|
||||
[TrainerPoolTier.RARE]: [ Species.TINKATON, Species.HISUI_LILLIGANT ]
|
||||
};
|
||||
}
|
||||
case "star_1": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.MURKROW, Species.SEEDOT, Species.CACNEA, Species.STUNKY, Species.SANDILE, Species.NYMBLE, Species.MASCHIFF, Species.GALAR_ZIGZAGOON ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.UMBREON, Species.SNEASEL, Species.CORPHISH, Species.ZORUA, Species.INKAY, Species.BOMBIRDIER ],
|
||||
[TrainerPoolTier.RARE]: [ Species.DEINO, Species.SPRIGATITO ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.SHIFTRY, Species.CACTURNE, Species.HONCHKROW, Species.SKUNTANK, Species.KROOKODILE, Species.OBSTAGOON, Species.LOKIX, Species.MABOSSTIFF ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.UMBREON, Species.CRAWDAUNT, Species.WEAVILE, Species.ZOROARK, Species.MALAMAR, Species.BOMBIRDIER ],
|
||||
[TrainerPoolTier.RARE]: [ Species.HYDREIGON, Species.MEOWSCARADA ]
|
||||
};
|
||||
}
|
||||
case "star_2": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.HOUNDOUR, Species.NUMEL, Species.LITWICK, Species.FLETCHLING, Species.LITLEO, Species.ROLYCOLY, Species.CAPSAKID ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.PONYTA, Species.FLAREON, Species.MAGBY, Species.TORKOAL, Species.SALANDIT, Species.TURTONATOR ],
|
||||
[TrainerPoolTier.RARE]: [ Species.LARVESTA, Species.FUECOCO ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.ARCANINE, Species.HOUNDOOM, Species.CAMERUPT, Species.CHANDELURE, Species.TALONFLAME, Species.PYROAR, Species.COALOSSAL, Species.SCOVILLAIN ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.RAPIDASH, Species.FLAREON, Species.TORKOAL, Species.MAGMORTAR, Species.SALAZZLE, Species.TURTONATOR ],
|
||||
[TrainerPoolTier.RARE]: [ Species.VOLCARONA, Species.SKELEDIRGE ]
|
||||
};
|
||||
}
|
||||
case "star_3": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.ZUBAT, Species.GRIMER, Species.STUNKY, Species.FOONGUS, Species.MAREANIE, Species.TOXEL, Species.SHROODLE, Species.PALDEA_WOOPER ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.GASTLY, Species.SEVIPER, Species.SKRELP, Species.ALOLA_GRIMER, Species.GALAR_SLOWPOKE, Species.HISUI_QWILFISH ],
|
||||
[TrainerPoolTier.RARE]: [ Species.GLIMMET, Species.BULBASAUR ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.MUK, Species.CROBAT, Species.SKUNTANK, Species.AMOONGUSS, Species.TOXAPEX, Species.TOXTRICITY, Species.GRAFAIAI, Species.CLODSIRE ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.GENGAR, Species.SEVIPER, Species.DRAGALGE, Species.OVERQWIL, Species.ALOLA_MUK, Species.GALAR_SLOWBRO ],
|
||||
[TrainerPoolTier.RARE]: [ Species.GLIMMORA, Species.VENUSAUR ]
|
||||
};
|
||||
}
|
||||
case "star_4": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.CLEFFA, Species.IGGLYBUFF, Species.AZURILL, Species.COTTONEE, Species.FLABEBE, Species.HATENNA, Species.IMPIDIMP, Species.TINKATINK ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.TOGEPI, Species.GARDEVOIR, Species.SYLVEON, Species.KLEFKI, Species.MIMIKYU, Species.ALOLA_VULPIX ],
|
||||
[TrainerPoolTier.RARE]: [ Species.GALAR_PONYTA, Species.POPPLIO ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.CLEFABLE, Species.WIGGLYTUFF, Species.AZUMARILL, Species.WHIMSICOTT, Species.FLORGES, Species.HATTERENE, Species.GRIMMSNARL, Species.TINKATON ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.TOGEKISS, Species.GARDEVOIR, Species.SYLVEON, Species.KLEFKI, Species.MIMIKYU, Species.ALOLA_NINETALES ],
|
||||
[TrainerPoolTier.RARE]: [ Species.GALAR_RAPIDASH, Species.PRIMARINA ]
|
||||
};
|
||||
}
|
||||
case "star_5": {
|
||||
return {
|
||||
[TrainerPoolTier.COMMON]: [ Species.SHROOMISH, Species.MAKUHITA, Species.MEDITITE, Species.CROAGUNK, Species.SCRAGGY, Species.MIENFOO, Species.PAWMI, Species.PALDEA_TAUROS ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.RIOLU, Species.TIMBURR, Species.HAWLUCHA, Species.PASSIMIAN, Species.FALINKS, Species.FLAMIGO ],
|
||||
[TrainerPoolTier.RARE]: [ Species.JANGMO_O, Species.QUAXLY ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.BRELOOM, Species.HARIYAMA, Species.MEDICHAM, Species.TOXICROAK, Species.SCRAFTY, Species.MIENSHAO, Species.PAWMOT, Species.PALDEA_TAUROS ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.LUCARIO, Species.CONKELDURR, Species.HAWLUCHA, Species.PASSIMIAN, Species.FALINKS, Species.FLAMIGO ],
|
||||
[TrainerPoolTier.RARE]: [ Species.KOMMO_O, Species.QUAQUAVAL ]
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -851,10 +935,7 @@ export class TrainerConfig {
|
||||
this.setHasVoucher(true);
|
||||
this.setBattleBgm("battle_unova_gym");
|
||||
this.setVictoryBgm("victory_gym");
|
||||
this.setGenModifiersFunc(party => {
|
||||
const waveIndex = globalScene.currentBattle.waveIndex;
|
||||
return getRandomTeraModifiers(party, waveIndex >= 100 ? 1 : 0, specialtyTypes.length ? specialtyTypes : undefined);
|
||||
});
|
||||
this.setRandomTeraModifiers(() => globalScene.currentBattle.waveIndex >= 100 ? 1 : 0);
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -910,7 +991,7 @@ export class TrainerConfig {
|
||||
this.setHasVoucher(true);
|
||||
this.setBattleBgm("battle_unova_elite");
|
||||
this.setVictoryBgm("victory_gym");
|
||||
this.setGenModifiersFunc(party => getRandomTeraModifiers(party, 1, specialtyTypes.length ? specialtyTypes : undefined));
|
||||
this.setRandomTeraModifiers(() => 1);
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -1197,16 +1278,6 @@ function getSpeciesFilterRandomPartyMemberFunc(
|
||||
};
|
||||
}
|
||||
|
||||
function getRandomTeraModifiers(party: EnemyPokemon[], count: number, types?: Type[]): PersistentModifier[] {
|
||||
const ret: PersistentModifier[] = [];
|
||||
const partyMemberIndexes = new Array(party.length).fill(null).map((_, i) => i);
|
||||
for (let t = 0; t < Math.min(count, party.length); t++) {
|
||||
const randomIndex = Utils.randSeedItem(partyMemberIndexes);
|
||||
partyMemberIndexes.splice(partyMemberIndexes.indexOf(randomIndex), 1);
|
||||
ret.push(modifierTypes.TERA_SHARD().generateType([], [ Utils.randSeedItem(types ? types : party[randomIndex].getTypes()) ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); // TODO: is the bang correct?
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
type SignatureSpecies = {
|
||||
[key in string]: (Species | Species[])[];
|
||||
@ -1500,9 +1571,9 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
),
|
||||
[TrainerType.ROCKET_GRUNT]: new TrainerConfig(++t).setHasGenders("Rocket Grunt Female").setHasDouble("Rocket Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate())
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.WEEDLE, Species.RATTATA, Species.EKANS, Species.SANDSHREW, Species.ZUBAT, Species.GEODUDE, Species.KOFFING, Species.GRIMER, Species.ODDISH, Species.SLOWPOKE ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.GYARADOS, Species.LICKITUNG, Species.TAUROS, Species.MANKEY, Species.SCYTHER, Species.ELEKID, Species.MAGBY, Species.CUBONE, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB, Species.MAGNEMITE ],
|
||||
[TrainerPoolTier.RARE]: [ Species.PORYGON, Species.ALOLA_RATTATA, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE, Species.PALDEA_TAUROS, Species.OMANYTE, Species.KABUTO ],
|
||||
[TrainerPoolTier.COMMON]: [ Species.WEEDLE, Species.RATTATA, Species.EKANS, Species.SANDSHREW, Species.ZUBAT, Species.ODDISH, Species.GEODUDE, Species.SLOWPOKE, Species.GRIMER, Species.KOFFING ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.MANKEY, Species.GROWLITHE, Species.MAGNEMITE, Species.GASTLY, Species.VOLTORB, Species.EXEGGCUTE, Species.CUBONE, Species.LICKITUNG, Species.SCYTHER, Species.TAUROS, Species.GYARADOS, Species.MURKROW, Species.ELEKID, Species.MAGBY ],
|
||||
[TrainerPoolTier.RARE]: [ Species.PORYGON, Species.OMANYTE, Species.KABUTO, Species.ALOLA_RATTATA, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GEODUDE, Species.ALOLA_GRIMER, Species.PALDEA_TAUROS ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.DRATINI, Species.LARVITAR ]
|
||||
}),
|
||||
[TrainerType.ARCHER]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("rocket_admin", "rocket", [ Species.HOUNDOOM ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
@ -1511,71 +1582,71 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
[TrainerType.PETREL]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("rocket_admin", "rocket", [ Species.WEEZING ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.MAGMA_GRUNT]: new TrainerConfig(++t).setHasGenders("Magma Grunt Female").setHasDouble("Magma Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate())
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.SLUGMA, Species.POOCHYENA, Species.NUMEL, Species.ZIGZAGOON, Species.DIGLETT, Species.MAGBY, Species.TORKOAL, Species.GROWLITHE, Species.BALTOY ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.SOLROCK, Species.HIPPOPOTAS, Species.SANDACONDA, Species.PHANPY, Species.ROLYCOLY, Species.GLIGAR, Species.RHYHORN, Species.HEATMOR ],
|
||||
[TrainerPoolTier.RARE]: [ Species.TRAPINCH, Species.LILEEP, Species.ANORITH, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON, Species.TOEDSCOOL ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.CAPSAKID, Species.CHARCADET ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.DIGLETT, Species.GROWLITHE, Species.SLUGMA, Species.MAGBY, Species.POOCHYENA, Species.ZIGZAGOON, Species.NUMEL, Species.TORKOAL, Species.BALTOY ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.RHYHORN, Species.GLIGAR, Species.PHANPY, Species.SOLROCK, Species.HIPPOPOTAS, Species.HEATMOR, Species.ROLYCOLY, Species.SILICOBRA ],
|
||||
[TrainerPoolTier.RARE]: [ Species.ARON, Species.TRAPINCH, Species.LILEEP, Species.ANORITH, Species.TURTONATOR, Species.TOEDSCOOL, Species.HISUI_GROWLITHE ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.CHARCADET, Species.CAPSAKID ]
|
||||
}),
|
||||
[TrainerType.TABITHA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("magma_admin", "magma", [ Species.CAMERUPT ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.COURTNEY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("magma_admin_female", "magma", [ Species.CAMERUPT ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.AQUA_GRUNT]: new TrainerConfig(++t).setHasGenders("Aqua Grunt Female").setHasDouble("Aqua Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate())
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.CARVANHA, Species.WAILMER, Species.ZIGZAGOON, Species.LOTAD, Species.CORPHISH, Species.SPHEAL, Species.REMORAID, Species.QWILFISH, Species.BARBOACH ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.AZURILL, Species.CLOBBOPUS, Species.HORSEA ],
|
||||
[TrainerPoolTier.RARE]: [ Species.MANTYKE, Species.DHELMISE, Species.HISUI_QWILFISH, Species.ARROKUDA, Species.PALDEA_WOOPER, Species.SKRELP ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.DONDOZO, Species.BASCULEGION ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.QWILFISH, Species.REMORAID, Species.ZIGZAGOON, Species.LOTAD, Species.CARVANHA, Species.WAILMER, Species.BARBOACH, Species.CORPHISH, Species.SPHEAL ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.TENTACOOL, Species.HORSEA, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.AZURILL, Species.CLAMPERL, Species.CLOBBOPUS ],
|
||||
[TrainerPoolTier.RARE]: [ Species.MANTYKE, Species.SKRELP, Species.DHELMISE, Species.ARROKUDA, Species.HISUI_QWILFISH, Species.PALDEA_WOOPER ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.BASCULEGION, Species.DONDOZO ]
|
||||
}),
|
||||
[TrainerType.MATT]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("aqua_admin", "aqua", [ Species.SHARPEDO ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.SHELLY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("aqua_admin_female", "aqua", [ Species.SHARPEDO ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.GALACTIC_GRUNT]: new TrainerConfig(++t).setHasGenders("Galactic Grunt Female").setHasDouble("Galactic Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate())
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.GLAMEOW, Species.STUNKY, Species.CROAGUNK, Species.SHINX, Species.WURMPLE, Species.BRONZOR, Species.DRIFLOON, Species.BURMY, Species.CARNIVINE ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.LICKITUNG, Species.RHYHORN, Species.TANGELA, Species.ZUBAT, Species.YANMA, Species.SKORUPI, Species.GLIGAR, Species.SWINUB ],
|
||||
[TrainerPoolTier.RARE]: [ Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.SNEASEL, Species.ELEKID, Species.MAGBY, Species.DUSKULL ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.ROTOM, Species.SPIRITOMB, Species.HISUI_SNEASEL ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.WURMPLE, Species.SHINX, Species.BURMY, Species.DRIFLOON, Species.GLAMEOW, Species.STUNKY, Species.BRONZOR, Species.CROAGUNK, Species.CARNIVINE ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.ZUBAT, Species.LICKITUNG, Species.RHYHORN, Species.TANGELA, Species.YANMA, Species.GLIGAR, Species.SWINUB, Species.SKORUPI ],
|
||||
[TrainerPoolTier.RARE]: [ Species.SNEASEL, Species.ELEKID, Species.MAGBY, Species.DUSKULL, Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.SPIRITOMB, Species.ROTOM, Species.HISUI_SNEASEL ]
|
||||
}),
|
||||
[TrainerType.JUPITER]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("galactic_commander_female", "galactic", [ Species.SKUNTANK ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.MARS]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("galactic_commander_female", "galactic", [ Species.PURUGLY ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.SATURN]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("galactic_commander", "galactic", [ Species.TOXICROAK ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.PLASMA_GRUNT]: new TrainerConfig(++t).setHasGenders("Plasma Grunt Female").setHasDouble("Plasma Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_plasma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate())
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.PATRAT, Species.LILLIPUP, Species.PURRLOIN, Species.SCRAFTY, Species.WOOBAT, Species.VANILLITE, Species.SANDILE, Species.TRUBBISH, Species.TYMPOLE ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.FRILLISH, Species.VENIPEDE, Species.GOLETT, Species.TIMBURR, Species.DARUMAKA, Species.FOONGUS, Species.JOLTIK, Species.CUBCHOO, Species.KLINK ],
|
||||
[TrainerPoolTier.RARE]: [ Species.PAWNIARD, Species.RUFFLET, Species.VULLABY, Species.ZORUA, Species.DRILBUR, Species.MIENFOO, Species.DURANT, Species.BOUFFALANT ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.DRUDDIGON, Species.HISUI_ZORUA, Species.AXEW, Species.DEINO ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.PATRAT, Species.LILLIPUP, Species.PURRLOIN, Species.WOOBAT, Species.TYMPOLE, Species.SANDILE, Species.SCRAGGY, Species.TRUBBISH, Species.VANILLITE ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.TIMBURR, Species.VENIPEDE, Species.DARUMAKA, Species.FOONGUS, Species.FRILLISH, Species.JOLTIK, Species.KLINK, Species.CUBCHOO, Species.GOLETT ],
|
||||
[TrainerPoolTier.RARE]: [ Species.DRILBUR, Species.ZORUA, Species.MIENFOO, Species.PAWNIARD, Species.BOUFFALANT, Species.RUFFLET, Species.VULLABY, Species.DURANT ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.AXEW, Species.DRUDDIGON, Species.DEINO, Species.HISUI_ZORUA ]
|
||||
}),
|
||||
[TrainerType.ZINZOLIN]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("plasma_sage", "plasma", [ Species.CRYOGONAL ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_plasma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.COLRESS]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("plasma_boss", "plasma_2", [ Species.KLINKLANG ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_colress").setMixedBattleBgm("battle_colress").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.FLARE_GRUNT]: new TrainerConfig(++t).setHasGenders("Flare Grunt Female").setHasDouble("Flare Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate())
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.PONYTA, Species.INKAY, Species.HOUNDOUR, Species.SKORUPI, Species.SCRAFTY, Species.CROAGUNK, Species.SCATTERBUG, Species.ESPURR ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.HELIOPTILE, Species.ELECTRIKE, Species.SKRELP, Species.PANCHAM, Species.PURRLOIN, Species.POOCHYENA, Species.BINACLE, Species.CLAUNCHER, Species.PUMPKABOO, Species.PHANTUMP, Species.FOONGUS ],
|
||||
[TrainerPoolTier.RARE]: [ Species.LITWICK, Species.SNEASEL, Species.PAWNIARD, Species.SLIGGOO ],
|
||||
[TrainerPoolTier.COMMON]: [ Species.PONYTA, Species.HOUNDOUR, Species.SKORUPI, Species.CROAGUNK, Species.SCRAGGY, Species.FLETCHLING, Species.SCATTERBUG, Species.LITLEO, Species.ESPURR, Species.INKAY ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.POOCHYENA, Species.ELECTRIKE, Species.PURRLOIN, Species.FOONGUS, Species.PANCHAM, Species.BINACLE, Species.SKRELP, Species.CLAUNCHER, Species.HELIOPTILE, Species.PHANTUMP, Species.PUMPKABOO ],
|
||||
[TrainerPoolTier.RARE]: [ Species.SNEASEL, Species.LITWICK, Species.PAWNIARD, Species.SLIGGOO ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.NOIBAT, Species.HISUI_SLIGGOO, Species.HISUI_AVALUGG ]
|
||||
}),
|
||||
[TrainerType.BRYONY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("flare_admin_female", "flare", [ Species.LIEPARD ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.XEROSIC]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("flare_admin", "flare", [ Species.MALAMAR ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.AETHER_GRUNT]: new TrainerConfig(++t).setHasGenders("Aether Grunt Female").setHasDouble("Aether Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aether_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate())
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.PIKIPEK, Species.ROCKRUFF, Species.ALOLA_DIGLETT, Species.ALOLA_EXEGGUTOR, Species.YUNGOOS, Species.CORSOLA, Species.ALOLA_GEODUDE, Species.ALOLA_RAICHU, Species.BOUNSWEET, Species.LILLIPUP, Species.KOMALA, Species.MORELULL, Species.COMFEY, Species.TOGEDEMARU ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.POLIWAG, Species.STUFFUL, Species.ORANGURU, Species.PASSIMIAN, Species.BRUXISH, Species.MINIOR, Species.WISHIWASHI, Species.ALOLA_SANDSHREW, Species.ALOLA_VULPIX, Species.CRABRAWLER, Species.CUTIEFLY, Species.ORICORIO, Species.MUDBRAY, Species.PYUKUMUKU, Species.ALOLA_MAROWAK ],
|
||||
[TrainerPoolTier.RARE]: [ Species.GALAR_CORSOLA, Species.TURTONATOR, Species.MIMIKYU, Species.MAGNEMITE, Species.DRAMPA ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.JANGMO_O, Species.PORYGON ]
|
||||
[TrainerPoolTier.COMMON]: [ Species.CORSOLA, Species.LILLIPUP, Species.PIKIPEK, Species.YUNGOOS, Species.ROCKRUFF, Species.MORELULL, Species.BOUNSWEET, Species.COMFEY, Species.KOMALA, Species.TOGEDEMARU, Species.ALOLA_RAICHU, Species.ALOLA_DIGLETT, Species.ALOLA_GEODUDE, Species.ALOLA_EXEGGUTOR ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.POLIWAG, Species.CRABRAWLER, Species.ORICORIO, Species.CUTIEFLY, Species.WISHIWASHI, Species.MUDBRAY, Species.STUFFUL, Species.ORANGURU, Species.PASSIMIAN, Species.PYUKUMUKU, Species.MINIOR, Species.BRUXISH, Species.ALOLA_SANDSHREW, Species.ALOLA_VULPIX, Species.ALOLA_MAROWAK ],
|
||||
[TrainerPoolTier.RARE]: [ Species.MAGNEMITE, Species.TURTONATOR, Species.MIMIKYU, Species.DRAMPA, Species.GALAR_CORSOLA ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.PORYGON, Species.JANGMO_O ]
|
||||
}),
|
||||
[TrainerType.FABA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("aether_admin", "aether", [ Species.HYPNO ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aether_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.SKULL_GRUNT]: new TrainerConfig(++t).setHasGenders("Skull Grunt Female").setHasDouble("Skull Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_skull_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate())
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.SALANDIT, Species.ALOLA_RATTATA, Species.EKANS, Species.ALOLA_MEOWTH, Species.SCRAGGY, Species.KOFFING, Species.ALOLA_GRIMER, Species.MAREANIE, Species.SPINARAK, Species.TRUBBISH, Species.DROWZEE ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.FOMANTIS, Species.SABLEYE, Species.SANDILE, Species.HOUNDOUR, Species.ALOLA_MAROWAK, Species.GASTLY, Species.PANCHAM, Species.ZUBAT, Species.VENIPEDE, Species.VULLABY ],
|
||||
[TrainerPoolTier.RARE]: [ Species.SANDYGAST, Species.PAWNIARD, Species.MIMIKYU, Species.DHELMISE, Species.WISHIWASHI, Species.NYMBLE ],
|
||||
[TrainerPoolTier.COMMON]: [ Species.EKANS, Species.DROWZEE, Species.KOFFING, Species.SPINARAK, Species.SCRAGGY, Species.TRUBBISH, Species.MAREANIE, Species.SALANDIT, Species.ALOLA_RATTATA, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.ZUBAT, Species.GASTLY, Species.HOUNDOUR, Species.SABLEYE, Species.VENIPEDE, Species.SANDILE, Species.VULLABY, Species.PANCHAM, Species.FOMANTIS, Species.ALOLA_MAROWAK ],
|
||||
[TrainerPoolTier.RARE]: [ Species.PAWNIARD, Species.WISHIWASHI, Species.SANDYGAST, Species.MIMIKYU, Species.DHELMISE, Species.NYMBLE ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.GRUBBIN, Species.DEWPIDER ]
|
||||
}),
|
||||
[TrainerType.PLUMERIA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("skull_admin", "skull", [ Species.SALAZZLE ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_skull_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
[TrainerType.MACRO_GRUNT]: new TrainerConfig(++t).setHasGenders("Macro Grunt Female").setHasDouble("Macro Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_macro_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate())
|
||||
.setSpeciesPools({
|
||||
[TrainerPoolTier.COMMON]: [ Species.CUFANT, Species.GALAR_MEOWTH, Species.KLINK, Species.ROOKIDEE, Species.CRAMORANT, Species.GALAR_ZIGZAGOON, Species.SKWOVET, Species.STEELIX, Species.MAWILE, Species.FERROSEED ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.DRILBUR, Species.MAGNEMITE, Species.HATENNA, Species.ARROKUDA, Species.APPLIN, Species.GALAR_PONYTA, Species.GALAR_YAMASK, Species.SINISTEA, Species.RIOLU ],
|
||||
[TrainerPoolTier.RARE]: [ Species.FALINKS, Species.BELDUM, Species.GALAR_FARFETCHD, Species.GALAR_MR_MIME, Species.HONEDGE, Species.SCIZOR, Species.GALAR_DARUMAKA ],
|
||||
[TrainerPoolTier.COMMON]: [ Species.STEELIX, Species.MAWILE, Species.FERROSEED, Species.KLINK, Species.SKWOVET, Species.ROOKIDEE, Species.CRAMORANT, Species.CUFANT, Species.GALAR_MEOWTH, Species.GALAR_ZIGZAGOON ],
|
||||
[TrainerPoolTier.UNCOMMON]: [ Species.MAGNEMITE, Species.RIOLU, Species.DRILBUR, Species.APPLIN, Species.ARROKUDA, Species.SINISTEA, Species.HATENNA, Species.GALAR_PONYTA, Species.GALAR_YAMASK ],
|
||||
[TrainerPoolTier.RARE]: [ Species.SCIZOR, Species.BELDUM, Species.HONEDGE, Species.FALINKS, Species.GALAR_FARFETCHD, Species.GALAR_MR_MIME, Species.GALAR_DARUMAKA ],
|
||||
[TrainerPoolTier.SUPER_RARE]: [ Species.DURALUDON, Species.DREEPY ]
|
||||
}),
|
||||
[TrainerType.OLEANA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("macro_admin", "macro", [ Species.GARBODOR ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_oleana").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(() => getEvilGruntPartyTemplate()),
|
||||
@ -1747,10 +1818,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateName();
|
||||
p.gender = Gender.MALE;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[3];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(3),
|
||||
[TrainerType.RED]: new TrainerConfig(++t).initForChampion(true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion").setHasDouble("red_blue_double").setDoubleTrainerType(TrainerType.BLUE).setDoubleTitle("champion_double")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PIKACHU ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 8; // G-Max Pikachu
|
||||
@ -1774,10 +1842,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateName();
|
||||
p.gender = Gender.MALE;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[3];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(3),
|
||||
[TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t).setName("Lance").initForChampion(true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GYARADOS, Species.KINGDRA ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.AERODACTYL ]))
|
||||
@ -1787,16 +1852,15 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateName();
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.CHARIZARD ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.TYRANITAR, Species.GARCHOMP, Species.KOMMO_O ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.TYRANITAR, Species.GARCHOMP, Species.KOMMO_O ], TrainerSlot.TRAINER, true, p => {
|
||||
p.teraType = p.species.type1;
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.DRAGONITE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.gender = Gender.MALE;
|
||||
p.setBoss(true, 2);
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[4];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(4),
|
||||
[TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(true).setBattleBgm("battle_hoenn_champion_g5").setMixedBattleBgm("battle_hoenn_champion_g6").setHasDouble("steven_wallace_double").setDoubleTrainerType(TrainerType.WALLACE).setDoubleTitle("champion_double")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SKARMORY ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CRADILY, Species.ARMALDO ]))
|
||||
@ -1814,10 +1878,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.generateName();
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[4];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(4),
|
||||
[TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(true).setBattleBgm("battle_hoenn_champion_g5").setMixedBattleBgm("battle_hoenn_champion_g6").setHasDouble("wallace_steven_double").setDoubleTrainerType(TrainerType.STEVEN).setDoubleTitle("champion_double")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PELIPPER ], TrainerSlot.TRAINER, true, p => {
|
||||
p.abilityIndex = 1; // Drizzle
|
||||
@ -1840,10 +1901,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.gender = Gender.FEMALE;
|
||||
p.setBoss(true, 2);
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[4];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(4),
|
||||
[TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(false).setBattleBgm("battle_sinnoh_champion").setMixedBattleBgm("battle_sinnoh_champion")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SPIRITOMB ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -1853,7 +1911,9 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.MILOTIC, Species.ROSERADE, Species.HISUI_ARCANINE ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.MILOTIC, Species.ROSERADE, Species.HISUI_ARCANINE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.teraType = p.species.type1;
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.TOGEKISS ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.setBoss(true, 2);
|
||||
@ -1864,10 +1924,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateName();
|
||||
p.gender = Gender.FEMALE;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[3];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(3),
|
||||
[TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(true).setHasDouble("alder_iris_double").setDoubleTrainerType(TrainerType.IRIS).setDoubleTitle("champion_double").setBattleBgm("battle_champion_alder").setMixedBattleBgm("battle_champion_alder")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BOUFFALANT, Species.BRAVIARY ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HISUI_LILLIGANT, Species.HISUI_ZOROARK, Species.BASCULEGION ], TrainerSlot.TRAINER, true, p => {
|
||||
@ -1882,16 +1939,15 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.CHANDELURE, Species.KROOKODILE, Species.REUNICLUS, Species.CONKELDURR ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.CHANDELURE, Species.KROOKODILE, Species.REUNICLUS, Species.CONKELDURR ], TrainerSlot.TRAINER, true, p => {
|
||||
p.teraType = p.species.speciesId === Species.KROOKODILE ? Type.DARK : p.species.type1;
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.VOLCARONA ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.gender = Gender.MALE;
|
||||
p.setBoss(true, 2);
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const pokemon = party[4];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ pokemon.species.speciesId === Species.KROOKODILE ? pokemon.species.type2 : pokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(pokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(4),
|
||||
[TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(false).setBattleBgm("battle_champion_iris").setMixedBattleBgm("battle_champion_iris").setHasDouble("iris_alder_double").setDoubleTrainerType(TrainerType.ALDER).setDoubleTitle("champion_double")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.DRUDDIGON ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ARCHEOPS ]))
|
||||
@ -1899,7 +1955,9 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.SALAMENCE, Species.HYDREIGON, Species.ARCHALUDON ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.SALAMENCE, Species.HYDREIGON, Species.ARCHALUDON ], TrainerSlot.TRAINER, true, p => {
|
||||
p.teraType = Type.DRAGON;
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.LAPRAS ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 1; // G-Max Lapras
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -1911,10 +1969,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.gender = Gender.FEMALE;
|
||||
p.setBoss(true, 2);
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[3];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ Type.DRAGON ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(3),
|
||||
[TrainerType.DIANTHA]: new TrainerConfig(++t).initForChampion(false).setMixedBattleBgm("battle_kalos_champion")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.HAWLUCHA ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -1927,6 +1982,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TYRANTRUM, Species.AURORUS ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.abilityIndex = 2; // Rock Head Tyrantrum, Snow Warning Aurorus
|
||||
p.teraType = p.species.speciesId === Species.TYRANTRUM ? Type.DRAGON : Type.ICE;
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GOODRA ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -1938,10 +1994,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateName();
|
||||
p.gender = Gender.FEMALE;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[3];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type2 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(3),
|
||||
[TrainerType.KUKUI]: new TrainerConfig(++t).initForChampion(true).setMixedBattleBgm("battle_champion_kukui")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LYCANROC ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -1965,11 +2018,9 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.INCINEROAR, Species.HISUI_DECIDUEYE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.gender = Gender.MALE;
|
||||
p.teraType = p.species.speciesId === Species.INCINEROAR ? Type.DARK : Type.FIGHTING;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[5];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type2 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(5),
|
||||
[TrainerType.HAU]: new TrainerConfig(++t).initForChampion(true).setMixedBattleBgm("battle_alola_champion")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ALOLA_RAICHU ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -1982,6 +2033,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TAPU_LELE, Species.TAPU_BULU ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.teraType = p.species.type1;
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.ZYGARDE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 1; // Zygarde 10% forme, Aura Break
|
||||
@ -1993,10 +2045,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.setBoss(true, 2);
|
||||
p.gender = p.species.speciesId === Species.PRIMARINA ? Gender.FEMALE : Gender.MALE;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[3];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(3),
|
||||
[TrainerType.LEON]: new TrainerConfig(++t).initForChampion(true).setMixedBattleBgm("battle_galar_champion")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AEGISLASH ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2017,10 +2066,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateName();
|
||||
p.gender = Gender.MALE;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[3];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(3),
|
||||
[TrainerType.MUSTARD]: new TrainerConfig(++t).initForChampion(true).setMixedBattleBgm("battle_mustard")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CORVIKNIGHT ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2033,6 +2079,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.teraType = Type.PSYCHIC;
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GALAR_DARMANITAN ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2050,10 +2097,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.gender = Gender.MALE;
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[2];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type2 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(2),
|
||||
[TrainerType.GEETA]: new TrainerConfig(++t).initForChampion(false).setMixedBattleBgm("battle_champion_geeta")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GLIMMORA ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2070,11 +2114,9 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KINGAMBIT ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.abilityIndex = 1; // Supreme Overlord
|
||||
p.teraType = Type.FLYING;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[5];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ Type.FLYING ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(5),
|
||||
[TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion(false).setMixedBattleBgm("battle_champion_nemona")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LYCANROC ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = 0; // Midday form
|
||||
@ -2086,16 +2128,15 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GHOLDENGO ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.ARMAROUGE, Species.CERULEDGE ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.ARMAROUGE, Species.CERULEDGE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.teraType = p.species.speciesId === Species.ARMAROUGE ? Type.PSYCHIC : Type.GHOST;
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.gender = Gender.MALE;
|
||||
p.setBoss(true, 2);
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[4];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type2 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(4),
|
||||
[TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion(true).setMixedBattleBgm("battle_champion_kieran")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.POLIWRATH, Species.POLITOED ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2117,7 +2158,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.OGERPON ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = Utils.randSeedInt(4, 4); // Random Ogerpon Tera Mask
|
||||
p.formIndex = Utils.randSeedInt(4); // Random Ogerpon Tera Mask
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
if (!p.moveset.some(move => !Utils.isNullOrUndefined(move) && move.moveId === Moves.IVY_CUDGEL)) { // Check if Ivy Cudgel is in the moveset, if not, replace the first move with Ivy Cudgel.
|
||||
@ -2129,17 +2170,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.gender = Gender.MALE;
|
||||
p.setBoss(true, 2);
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const starter = party[4];
|
||||
let teraShardType: Type;
|
||||
const pokemonType2 = starter.species.forms[starter.formIndex].type2;
|
||||
if (starter.formIndex === 4 || Utils.isNullOrUndefined(pokemonType2)) {
|
||||
teraShardType = starter.species.type1;
|
||||
} else {
|
||||
teraShardType = pokemonType2;
|
||||
}
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraShardType ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ];
|
||||
}),
|
||||
.setInstantTera(4),
|
||||
|
||||
[TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setMixedBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL)
|
||||
.setModifierRewardFuncs(() => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE)
|
||||
@ -2161,20 +2192,22 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
|
||||
.setSpeciesFilter(species => species.baseTotal >= 540),
|
||||
[TrainerType.RIVAL_4]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(1.75).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival_2").setMixedBattleBgm("battle_rival_2").setPartyTemplates(trainerPartyTemplates.RIVAL_4)
|
||||
.setModifierRewardFuncs(() => modifierTypes.TERA_ORB)
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ], TrainerSlot.TRAINER, true,
|
||||
(p => p.abilityIndex = 0)))
|
||||
(p => {
|
||||
p.abilityIndex = 0;
|
||||
p.teraType = p.species.type1;
|
||||
})))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ], TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
|
||||
.setSpeciesFilter(species => species.baseTotal >= 540)
|
||||
.setGenModifiersFunc(party => {
|
||||
const starter = party[0];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ starter.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ]; // TODO: is the bang correct?
|
||||
}),
|
||||
.setInstantTera(0),
|
||||
[TrainerType.RIVAL_5]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival_3").setMixedBattleBgm("battle_rival_3").setPartyTemplates(trainerPartyTemplates.RIVAL_5)
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ], TrainerSlot.TRAINER, true,
|
||||
p => {
|
||||
p.setBoss(true, 2);
|
||||
p.abilityIndex = 0;
|
||||
p.teraType = p.species.type1;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ], TrainerSlot.TRAINER, true))
|
||||
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
|
||||
@ -2185,15 +2218,13 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.shiny = true;
|
||||
p.variant = 1;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const starter = party[0];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ starter.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ]; //TODO: is the bang correct?
|
||||
}),
|
||||
.setInstantTera(0),
|
||||
[TrainerType.RIVAL_6]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(3).setEncounterBgm("final").setBattleBgm("battle_rival_3").setMixedBattleBgm("battle_rival_3").setPartyTemplates(trainerPartyTemplates.RIVAL_6)
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ], TrainerSlot.TRAINER, true,
|
||||
p => {
|
||||
p.setBoss(true, 3);
|
||||
p.abilityIndex = 0;
|
||||
p.teraType = p.species.type1;
|
||||
p.generateAndPopulateMoveset();
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ], TrainerSlot.TRAINER, true,
|
||||
@ -2212,10 +2243,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 1; // Mega Rayquaza
|
||||
p.generateName();
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const starter = party[0];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ starter.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ]; // TODO: is the bang correct?
|
||||
}),
|
||||
.setInstantTera(0),
|
||||
|
||||
[TrainerType.ROCKET_BOSS_GIOVANNI_1]: new TrainerConfig(t = TrainerType.ROCKET_BOSS_GIOVANNI_1).setName("Giovanni").initForEvilTeamLeader("Rocket Boss", []).setMixedBattleBgm("battle_rocket_boss").setVictoryBgm("victory_team_plasma")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PERSIAN ], TrainerSlot.TRAINER, true, p => {
|
||||
@ -2225,7 +2253,11 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DUGTRIO, Species.ALOLA_DUGTRIO ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HONCHKROW ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.NIDOQUEEN, Species.NIDOKING ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.RHYPERIOR ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.RHYPERIOR ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.abilityIndex = 1; // Solid Rock
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2234,20 +2266,32 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateName();
|
||||
})),
|
||||
[TrainerType.ROCKET_BOSS_GIOVANNI_2]: new TrainerConfig(++t).setName("Giovanni").initForEvilTeamLeader("Rocket Boss", [], true).setMixedBattleBgm("battle_rocket_boss").setVictoryBgm("victory_team_plasma")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.TYRANITAR, Species.IRON_THORNS ], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.TYRANITAR ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HIPPOWDON ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.GARCHOMP, Species.EXCADRILL ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GASTRODON, Species.SEISMITOAD ], TrainerSlot.TRAINER, true, p => {
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GASTRODON, Species.SEISMITOAD ], TrainerSlot.TRAINER, true, p => {
|
||||
if (p.species.speciesId === Species.GASTRODON) {
|
||||
p.abilityIndex = 0; // Storm Drain
|
||||
} else if (p.species.speciesId === Species.SEISMITOAD) {
|
||||
p.abilityIndex = 2; // Water Absorb
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.GARCHOMP, Species.EXCADRILL ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
if (p.species.speciesId === Species.GARCHOMP) {
|
||||
p.abilityIndex = 2; // Rough Skin
|
||||
} else if (p.species.speciesId === Species.EXCADRILL) {
|
||||
p.abilityIndex = 0; // Sand Rush
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.RHYPERIOR ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.abilityIndex = 1; // Solid Rock
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2295,7 +2339,10 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.abilityIndex = 0; // Chlorophyll
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GREAT_TUSK ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GREAT_TUSK ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ROGUE_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.CAMERUPT ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2384,7 +2431,10 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MAGNEZONE ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.UXIE, Species.MESPRIT, Species.AZELF ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.UXIE, Species.MESPRIT, Species.AZELF ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ROGUE_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.HOUNDOOM ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
@ -2425,7 +2475,10 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.formIndex = 0;
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.KINGAMBIT ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.VOLCARONA, Species.IRON_MOTH ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.VOLCARONA, Species.IRON_MOTH ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ROGUE_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.HYDREIGON, Species.IRON_JUGULIS ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2448,7 +2501,14 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.gender = Gender.MALE;
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.DRAGALGE, Species.CLAWITZER ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.DRAGALGE, Species.CLAWITZER ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
if (p.species.speciesId === Species.DRAGALGE) {
|
||||
p.abilityIndex = 2; // Adaptability
|
||||
} else if (p.species.speciesId === Species.CLAWITZER) {
|
||||
p.abilityIndex = 0; // Mega Launcher
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GALLADE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.abilityIndex = 1; // Sharpness
|
||||
@ -2467,7 +2527,14 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.gender = Gender.MALE;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DRAGALGE, Species.CLAWITZER ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DRAGALGE, Species.CLAWITZER ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
if (p.species.speciesId === Species.DRAGALGE) {
|
||||
p.abilityIndex = 2; // Adaptability
|
||||
} else if (p.species.speciesId === Species.CLAWITZER) {
|
||||
p.abilityIndex = 0; // Mega Launcher
|
||||
}
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.AEGISLASH, Species.HISUI_GOODRA ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.IRON_VALIANT ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2477,7 +2544,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.formIndex = 1; // Mega Gyardos
|
||||
p.formIndex = 1; // Mega Gyarados
|
||||
p.generateName();
|
||||
p.gender = Gender.MALE;
|
||||
}))
|
||||
@ -2597,11 +2664,26 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
})),
|
||||
[TrainerType.ROSE]: new TrainerConfig(++t).setName("Rose").initForEvilTeamLeader("Macro Boss", []).setMixedBattleBgm("battle_macro_boss").setVictoryBgm("victory_team_plasma")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ARCHALUDON ]))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ESCAVALIER, Species.FERROTHORN ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SIRFETCHD, Species.MR_RIME ]))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.CORVIKNIGHT ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.KLINKLANG, Species.PERRSERKER ]))
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ARCHALUDON ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ESCAVALIER, Species.FERROTHORN ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SIRFETCHD, Species.MR_RIME ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.CORVIKNIGHT ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.KLINKLANG, Species.PERRSERKER ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.COPPERAJAH ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2614,13 +2696,21 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ARCHALUDON ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.AEGISLASH, Species.GHOLDENGO ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.AEGISLASH, Species.GHOLDENGO ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.DRACOZOLT, Species.DRACOVISH ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.abilityIndex = 1; //Strong Jaw Dracovish, Hustle Dracozolt
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.abilityIndex = 1; // Strong Jaw Dracovish, Hustle Dracozolt
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.MELMETAL ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.MELMETAL ]))
|
||||
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GALAR_ARTICUNO, Species.GALAR_ZAPDOS, Species.GALAR_MOLTRES ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2651,10 +2741,7 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
p.generateName();
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[4];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; //TODO: is the bang correct?
|
||||
}),
|
||||
.setInstantTera(4),
|
||||
[TrainerType.PENNY_2]: new TrainerConfig(++t).setName("Cassiopeia").initForEvilTeamLeader("Star Boss", [], true).setMixedBattleBgm("battle_star_boss").setVictoryBgm("victory_team_plasma")
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
@ -2666,7 +2753,10 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.formIndex = Utils.randSeedInt(5, 1); // Heat, Wash, Frost, Fan, or Mow
|
||||
}))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.RAIKOU, Species.ENTEI, Species.SUICUNE ]))
|
||||
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.RAIKOU, Species.ENTEI, Species.SUICUNE ], TrainerSlot.TRAINER, true, p => {
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => {
|
||||
p.formIndex = Utils.randSeedInt(5, 1); // Random Starmobile form
|
||||
p.generateAndPopulateMoveset();
|
||||
@ -2684,10 +2774,12 @@ export const trainerConfigs: TrainerConfigs = {
|
||||
p.generateName();
|
||||
p.pokeball = PokeballType.ULTRA_BALL;
|
||||
}))
|
||||
.setGenModifiersFunc(party => {
|
||||
const teraPokemon = party[0];
|
||||
return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; //TODO: is the bang correct?
|
||||
}),
|
||||
.setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.ZAMAZENTA ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 2);
|
||||
p.generateAndPopulateMoveset();
|
||||
p.pokeball = PokeballType.MASTER_BALL;
|
||||
}))
|
||||
.setInstantTera(0),
|
||||
[TrainerType.BUCK]: new TrainerConfig(++t).setName("Buck").initForStatTrainer([], true)
|
||||
.setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CLAYDOL ], TrainerSlot.TRAINER, true, p => {
|
||||
p.setBoss(true, 3);
|
||||
|
@ -44,6 +44,7 @@ export class Arena {
|
||||
public bgm: string;
|
||||
public ignoreAbilities: boolean;
|
||||
public ignoringEffectSource: BattlerIndex | null;
|
||||
public playerTerasUsed: number;
|
||||
/**
|
||||
* Saves the number of times a party pokemon faints during a arena encounter.
|
||||
* {@linkcode globalScene.currentBattle.enemyFaints} is the corresponding faint counter for the enemy (this resets every wave).
|
||||
@ -63,6 +64,7 @@ export class Arena {
|
||||
this.bgm = bgm;
|
||||
this.trainerPool = biomeTrainerPools[biome];
|
||||
this.updatePoolsForTimeOfDay();
|
||||
this.playerTerasUsed = 0;
|
||||
this.playerFaints = playerFaints;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,9 @@ export default class PokemonSpriteSparkleHandler {
|
||||
if (!s.visible || (s.parentContainer instanceof Pokemon && !s.parentContainer.parentContainer)) {
|
||||
continue;
|
||||
}
|
||||
if (!(s.parentContainer instanceof Pokemon) || !(s.parentContainer as Pokemon).isTerastallized) {
|
||||
continue;
|
||||
}
|
||||
const pokemon = s.parentContainer instanceof Pokemon ? s.parentContainer as Pokemon : null;
|
||||
const parent = (pokemon || s).parentContainer;
|
||||
const texture = s.texture;
|
||||
|
@ -52,7 +52,7 @@ import { getTypeDamageMultiplier, getTypeRgb } from "#app/data/type";
|
||||
import { Type } from "#enums/type";
|
||||
import { getLevelTotalExp } from "#app/data/exp";
|
||||
import { Stat, type PermanentStat, type BattleStat, type EffectiveStat, PERMANENT_STATS, BATTLE_STATS, EFFECTIVE_STATS } from "#enums/stat";
|
||||
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, BaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempStatStageBoosterModifier, TempCritBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonIncrementingStatModifier, EvoTrackerModifier, PokemonMultiHitModifier } from "#app/modifier/modifier";
|
||||
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, BaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempStatStageBoosterModifier, TempCritBoosterModifier, StatBoosterModifier, CritBoosterModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonIncrementingStatModifier, EvoTrackerModifier, PokemonMultiHitModifier } from "#app/modifier/modifier";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import { Gender } from "#app/data/gender";
|
||||
import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
|
||||
@ -79,7 +79,7 @@ import { DexAttr } from "#app/system/game-data";
|
||||
import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities";
|
||||
import { getNatureStatMultiplier } from "#app/data/nature";
|
||||
import type { SpeciesFormChange } from "#app/data/pokemon-forms";
|
||||
import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from "#app/data/pokemon-forms";
|
||||
import { SpeciesFormChangeActiveTrigger, SpeciesFormChangeLapseTeraTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from "#app/data/pokemon-forms";
|
||||
import { TerrainType } from "#app/data/terrain";
|
||||
import type { TrainerSlot } from "#app/data/trainer-config";
|
||||
import Overrides from "#app/overrides";
|
||||
@ -163,6 +163,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
public pokerus: boolean;
|
||||
public switchOutStatus: boolean;
|
||||
public evoCounter: number;
|
||||
public teraType: Type;
|
||||
public isTerastallized: boolean;
|
||||
public stellarTypesBoosted: Type[];
|
||||
|
||||
public fusionSpecies: PokemonSpecies | null;
|
||||
public fusionFormIndex: number;
|
||||
@ -172,6 +175,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
public fusionGender: Gender;
|
||||
public fusionLuck: number;
|
||||
public fusionCustomPokemonData: CustomPokemonData | null;
|
||||
public fusionTeraType: Type;
|
||||
|
||||
private summonDataPrimer: PokemonSummonData | null;
|
||||
|
||||
@ -200,7 +204,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
throw `Cannot create a player Pokemon for species '${species.getName(formIndex)}'`;
|
||||
}
|
||||
|
||||
const hiddenAbilityChance = new Utils.IntegerHolder(BASE_HIDDEN_ABILITY_CHANCE);
|
||||
const hiddenAbilityChance = new Utils.NumberHolder(BASE_HIDDEN_ABILITY_CHANCE);
|
||||
if (!this.hasTrainer()) {
|
||||
globalScene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance);
|
||||
}
|
||||
@ -269,8 +273,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.fusionGender = dataSource.fusionGender;
|
||||
this.fusionLuck = dataSource.fusionLuck;
|
||||
this.fusionCustomPokemonData = dataSource.fusionCustomPokemonData;
|
||||
this.fusionTeraType = dataSource.fusionTeraType;
|
||||
this.usedTMs = dataSource.usedTMs ?? [];
|
||||
this.customPokemonData = new CustomPokemonData(dataSource.customPokemonData);
|
||||
this.teraType = dataSource.teraType;
|
||||
this.isTerastallized = dataSource.isTerastallized;
|
||||
this.stellarTypesBoosted = dataSource.stellarTypesBoosted ?? [];
|
||||
} else {
|
||||
this.id = Utils.randSeedInt(4294967296);
|
||||
this.ivs = ivs || Utils.getIvsFromId(this.id);
|
||||
@ -319,6 +327,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
this.luck = (this.shiny ? this.variant + 1 : 0) + (this.fusionShiny ? this.fusionVariant + 1 : 0);
|
||||
this.fusionLuck = this.luck;
|
||||
|
||||
this.teraType = Utils.randSeedItem(this.getTypes(false, false, true));
|
||||
this.isTerastallized = false;
|
||||
this.stellarTypesBoosted = [];
|
||||
}
|
||||
|
||||
this.generateName();
|
||||
@ -355,7 +367,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
const getSprite = (hasShadow?: boolean) => {
|
||||
const ret = globalScene.addPokemonSprite(this, 0, 0, `pkmn__${this.isPlayer() ? "back__" : ""}sub`, undefined, true);
|
||||
ret.setOrigin(0.5, 1);
|
||||
ret.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: !!hasShadow, teraColor: getTypeRgb(this.getTeraType()) });
|
||||
ret.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: !!hasShadow, teraColor: getTypeRgb(this.getTeraType()), isTerastallized: this.isTerastallized });
|
||||
return ret;
|
||||
};
|
||||
|
||||
@ -723,7 +735,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
updateSpritePipelineData(): void {
|
||||
[ this.getSprite(), this.getTintSprite() ].filter(s => !!s).map(s => s.pipelineData["teraColor"] = getTypeRgb(this.getTeraType()));
|
||||
[ this.getSprite(), this.getTintSprite() ].filter(s => !!s).map(s => {
|
||||
s.pipelineData["teraColor"] = getTypeRgb(this.getTeraType());
|
||||
s.pipelineData["isTerastallized"] = this.isTerastallized;
|
||||
});
|
||||
this.updateInfo(true);
|
||||
}
|
||||
|
||||
@ -945,7 +960,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* @returns the final critical-hit stage value
|
||||
*/
|
||||
getCritStage(source: Pokemon, move: Move): number {
|
||||
const critStage = new Utils.IntegerHolder(0);
|
||||
const critStage = new Utils.NumberHolder(0);
|
||||
applyMoveAttrs(HighCritAttr, source, this, move, critStage);
|
||||
globalScene.applyModifiers(CritBoosterModifier, source.isPlayer(), source, critStage);
|
||||
globalScene.applyModifiers(TempCritBoosterModifier, source.isPlayer(), critStage);
|
||||
@ -1059,7 +1074,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
const baseStats = this.calculateBaseStats();
|
||||
// Using base stats, calculate and store stats one by one
|
||||
for (const s of PERMANENT_STATS) {
|
||||
const statHolder = new Utils.IntegerHolder(Math.floor(((2 * baseStats[s] + this.ivs[s]) * this.level) * 0.01));
|
||||
const statHolder = new Utils.NumberHolder(Math.floor(((2 * baseStats[s] + this.ivs[s]) * this.level) * 0.01));
|
||||
if (s === Stat.HP) {
|
||||
statHolder.value = statHolder.value + this.level + 10;
|
||||
globalScene.applyModifier(PokemonIncrementingStatModifier, this.isPlayer(), this, s, statHolder);
|
||||
@ -1208,6 +1223,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return this.fusionSpecies?.speciesId === species;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the {@linkcode Pokemon} has is the specified {@linkcode Species} or is fused with it.
|
||||
* @param species the pokemon {@linkcode Species} to check
|
||||
* @returns `true` if the pokemon is the species or is fused with it, `false` otherwise
|
||||
*/
|
||||
hasSpecies(species: Species): boolean {
|
||||
return this.species.speciesId === species || this.fusionSpecies?.speciesId === species;
|
||||
}
|
||||
|
||||
abstract isBoss(): boolean;
|
||||
|
||||
getMoveset(ignoreOverride?: boolean): (PokemonMove | null)[] {
|
||||
@ -1284,9 +1308,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
public getTypes(includeTeraType = false, forDefend: boolean = false, ignoreOverride: boolean = false): Type[] {
|
||||
const types: Type[] = [];
|
||||
|
||||
if (includeTeraType) {
|
||||
if (includeTeraType && this.isTerastallized) {
|
||||
const teraType = this.getTeraType();
|
||||
if (teraType !== Type.UNKNOWN) {
|
||||
if (this.isTerastallized && !(forDefend && teraType === Type.STELLAR)) { // Stellar tera uses its original types defensively
|
||||
types.push(teraType);
|
||||
if (forDefend) {
|
||||
return types;
|
||||
@ -1322,6 +1346,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
} else if (fusionType1 !== types[0]) {
|
||||
secondType = fusionType1;
|
||||
}
|
||||
|
||||
|
||||
if (secondType === Type.UNKNOWN && Utils.isNullOrUndefined(fusionType2)) { // If second pokemon was monotype and shared its primary type
|
||||
secondType = (customTypes && this.customPokemonData.types.length > 1 && this.customPokemonData.types[1] !== Type.UNKNOWN)
|
||||
? this.customPokemonData.types[1] : (speciesForm.type2 ?? Type.UNKNOWN);
|
||||
}
|
||||
} else {
|
||||
// If not a fusion, just get the second type from the species, checking for permanent changes from ME
|
||||
secondType = (customTypes && this.customPokemonData.types.length > 1 && this.customPokemonData.types[1] !== Type.UNKNOWN)
|
||||
@ -1584,23 +1614,31 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns the pokemon's current tera {@linkcode Type}, or `Type.UNKNOWN` if the pokemon is not terastallized
|
||||
* @returns the pokemon's current tera {@linkcode Type}
|
||||
*/
|
||||
public getTeraType(): Type {
|
||||
// I don't think this should be possible anymore, please report if you encounter this. --NightKev
|
||||
if (globalScene === undefined) {
|
||||
console.warn("Pokemon.getTeraType(): Global scene is not defined!");
|
||||
return Type.UNKNOWN;
|
||||
getTeraType(): Type {
|
||||
if (this.hasSpecies(Species.TERAPAGOS)) {
|
||||
return Type.STELLAR;
|
||||
} else if (this.hasSpecies(Species.OGERPON)) {
|
||||
const ogerponForm = this.species.speciesId === Species.OGERPON ? this.formIndex : this.fusionFormIndex;
|
||||
switch (ogerponForm) {
|
||||
case 0:
|
||||
case 4:
|
||||
return Type.GRASS;
|
||||
case 1:
|
||||
case 5:
|
||||
return Type.WATER;
|
||||
case 2:
|
||||
case 6:
|
||||
return Type.FIRE;
|
||||
case 3:
|
||||
case 7:
|
||||
return Type.ROCK;
|
||||
}
|
||||
} else if (this.hasSpecies(Species.SHEDINJA)) {
|
||||
return Type.BUG;
|
||||
}
|
||||
const teraModifier = globalScene.findModifier(m =>
|
||||
m instanceof TerastallizeModifier
|
||||
&& m.pokemonId === this.id
|
||||
&& m.getBattlesLeft() > 0, this.isPlayer()) as TerastallizeModifier;
|
||||
return teraModifier?.teraType ?? Type.UNKNOWN;
|
||||
}
|
||||
|
||||
public isTerastallized(): boolean {
|
||||
return this.getTeraType() !== Type.UNKNOWN;
|
||||
return this.teraType;
|
||||
}
|
||||
|
||||
public isGrounded(): boolean {
|
||||
@ -1742,7 +1780,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
*/
|
||||
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true, move?: Move): TypeDamageMultiplier {
|
||||
if (moveType === Type.STELLAR) {
|
||||
return this.isTerastallized() ? 2 : 1;
|
||||
return this.isTerastallized ? 2 : 1;
|
||||
}
|
||||
const types = this.getTypes(true, true);
|
||||
const arena = globalScene.arena;
|
||||
@ -2529,7 +2567,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* @return the stat stage multiplier to be used for effective stat calculation
|
||||
*/
|
||||
getStatStageMultiplier(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true, ignoreHeldItems: boolean = false): number {
|
||||
const statStage = new Utils.IntegerHolder(this.getStatStage(stat));
|
||||
const statStage = new Utils.NumberHolder(this.getStatStage(stat));
|
||||
const ignoreStatStage = new Utils.BooleanHolder(false);
|
||||
|
||||
if (opponent) {
|
||||
@ -2579,8 +2617,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const userAccStage = new Utils.IntegerHolder(this.getStatStage(Stat.ACC));
|
||||
const targetEvaStage = new Utils.IntegerHolder(target.getStatStage(Stat.EVA));
|
||||
const userAccStage = new Utils.NumberHolder(this.getStatStage(Stat.ACC));
|
||||
const targetEvaStage = new Utils.NumberHolder(target.getStatStage(Stat.EVA));
|
||||
|
||||
const ignoreAccStatStage = new Utils.BooleanHolder(false);
|
||||
const ignoreEvaStatStage = new Utils.BooleanHolder(false);
|
||||
@ -2759,7 +2797,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
/** Doubles damage if this Pokemon's last move was Glaive Rush */
|
||||
const glaiveRushMultiplier = new Utils.IntegerHolder(1);
|
||||
const glaiveRushMultiplier = new Utils.NumberHolder(1);
|
||||
if (this.getTag(BattlerTagType.RECEIVE_DOUBLE_DAMAGE)) {
|
||||
glaiveRushMultiplier.value = 2;
|
||||
}
|
||||
@ -2779,11 +2817,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
const matchesSourceType = sourceTypes.includes(moveType);
|
||||
/** A damage multiplier for when the attack is of the attacker's type and/or Tera type. */
|
||||
const stabMultiplier = new Utils.NumberHolder(1);
|
||||
if (matchesSourceType) {
|
||||
stabMultiplier.value += 0.5;
|
||||
}
|
||||
applyMoveAttrs(CombinedPledgeStabBoostAttr, source, this, move, stabMultiplier);
|
||||
if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === moveType) {
|
||||
if (matchesSourceType && moveType !== Type.STELLAR) {
|
||||
stabMultiplier.value += 0.5;
|
||||
}
|
||||
|
||||
@ -2791,6 +2825,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
applyAbAttrs(StabBoostAbAttr, source, null, simulated, stabMultiplier);
|
||||
}
|
||||
|
||||
applyMoveAttrs(CombinedPledgeStabBoostAttr, source, this, move, stabMultiplier);
|
||||
|
||||
if (source.isTerastallized && sourceTeraType === moveType && moveType !== Type.STELLAR) {
|
||||
stabMultiplier.value += 0.5;
|
||||
}
|
||||
|
||||
if (source.isTerastallized && source.teraType === Type.STELLAR && (!source.stellarTypesBoosted.includes(moveType) || source.hasSpecies(Species.TERAPAGOS))) {
|
||||
if (matchesSourceType) {
|
||||
stabMultiplier.value += 0.5;
|
||||
} else {
|
||||
stabMultiplier.value += 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
stabMultiplier.value = Math.min(stabMultiplier.value, 2.25);
|
||||
|
||||
/** Halves damage if the attacker is using a physical attack while burned */
|
||||
@ -3831,6 +3879,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
}
|
||||
|
||||
resetTera(): void {
|
||||
const wasTerastallized = this.isTerastallized;
|
||||
this.isTerastallized = false;
|
||||
this.stellarTypesBoosted = [];
|
||||
if (wasTerastallized) {
|
||||
this.updateSpritePipelineData();
|
||||
globalScene.triggerPokemonFormChange(this, SpeciesFormChangeLapseTeraTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
resetTurnData(): void {
|
||||
this.turnData = new PokemonTurnData();
|
||||
}
|
||||
@ -4036,6 +4094,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
}
|
||||
|
||||
if (fusionPixelColors.length === 0) { // ERROR HANDLING IS NOT OPTIONAL BUDDY
|
||||
console.log("Failed to create fusion palette");
|
||||
return;
|
||||
}
|
||||
|
||||
let paletteColors: Map<number, number>;
|
||||
let fusionPaletteColors: Map<number, number>;
|
||||
|
||||
@ -4049,8 +4112,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
Math.random = originalRandom;
|
||||
|
||||
paletteColors = paletteColors!; // tell TS compiler that paletteColors is defined!
|
||||
fusionPaletteColors = fusionPaletteColors!; // TS compiler that fusionPaletteColors is defined!
|
||||
paletteColors = paletteColors!; // erroneously tell TS compiler that paletteColors is defined!
|
||||
fusionPaletteColors = fusionPaletteColors!; // mischievously misinform TS compiler that fusionPaletteColors is defined!
|
||||
const [ palette, fusionPalette ] = [ paletteColors, fusionPaletteColors ]
|
||||
.map(paletteColors => {
|
||||
let keys = Array.from(paletteColors.keys()).sort((a: number, b: number) => paletteColors.get(a)! < paletteColors.get(b)! ? 1 : -1);
|
||||
@ -4589,6 +4652,7 @@ export class PlayerPokemon extends Pokemon {
|
||||
newPokemon.fusionVariant = this.fusionVariant;
|
||||
newPokemon.fusionGender = this.fusionGender;
|
||||
newPokemon.fusionLuck = this.fusionLuck;
|
||||
newPokemon.fusionTeraType = this.teraType;
|
||||
newPokemon.usedTMs = this.usedTMs;
|
||||
|
||||
globalScene.getPlayerParty().push(newPokemon);
|
||||
@ -4740,6 +4804,7 @@ export class EnemyPokemon extends Pokemon {
|
||||
public aiType: AiType;
|
||||
public bossSegments: number;
|
||||
public bossSegmentIndex: number;
|
||||
public initialTeamIndex: number;
|
||||
/** To indicate if the instance was populated with a dataSource -> e.g. loaded & populated from session data */
|
||||
public readonly isPopulatedFromDataSource: boolean;
|
||||
|
||||
@ -4749,6 +4814,7 @@ export class EnemyPokemon extends Pokemon {
|
||||
undefined, dataSource ? dataSource.nature : undefined, dataSource);
|
||||
|
||||
this.trainerSlot = trainerSlot;
|
||||
this.initialTeamIndex = globalScene.currentBattle?.enemyParty.length ?? 0;
|
||||
this.isPopulatedFromDataSource = !!dataSource; // if a dataSource is provided, then it was populated from dataSource
|
||||
if (boss) {
|
||||
this.setBoss(boss, dataSource?.bossSegments);
|
||||
|
@ -11,7 +11,8 @@ import {
|
||||
TrainerSlot,
|
||||
trainerConfigs,
|
||||
trainerPartyTemplates,
|
||||
signatureSpecies
|
||||
signatureSpecies,
|
||||
TeraAIMode
|
||||
} from "#app/data/trainer-config";
|
||||
import type { EnemyPokemon } from "#app/field/pokemon";
|
||||
import * as Utils from "#app/utils";
|
||||
@ -36,6 +37,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||
public partyTemplateIndex: number;
|
||||
public name: string;
|
||||
public partnerName: string;
|
||||
public originalIndexes: { [key: number]: number } = {};
|
||||
|
||||
constructor(trainerType: TrainerType, variant: TrainerVariant, partyTemplateIndex?: number, name?: string, partnerName?: string, trainerConfigOverride?: TrainerConfig) {
|
||||
super(globalScene, -72, 80);
|
||||
@ -546,6 +548,13 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||
return [];
|
||||
}
|
||||
|
||||
genAI(party: EnemyPokemon[]) {
|
||||
if (this.config.genAIFuncs) {
|
||||
this.config.genAIFuncs.forEach(f => f(party));
|
||||
}
|
||||
console.log("Generated AI funcs");
|
||||
}
|
||||
|
||||
loadAssets(): Promise<void> {
|
||||
return this.config.loadAssets(this.variant);
|
||||
}
|
||||
@ -667,4 +676,13 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
shouldTera(pokemon: EnemyPokemon): boolean {
|
||||
if (this.config.trainerAI.teraMode === TeraAIMode.INSTANT_TERA) {
|
||||
if (!pokemon.isTerastallized && this.config.trainerAI.instantTeras.includes(pokemon.initialTeamIndex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -103,6 +103,7 @@ export class LoadingScene extends SceneBase {
|
||||
this.loadImage("icon_tera", "ui");
|
||||
this.loadImage("type_tera", "ui");
|
||||
this.loadAtlas("type_bgs", "ui");
|
||||
this.loadAtlas("button_tera", "ui");
|
||||
this.loadImage("mystery_egg", "ui");
|
||||
this.loadImage("normal_memory", "ui");
|
||||
|
||||
|
@ -11,7 +11,7 @@ import { Type } from "#enums/type";
|
||||
import type { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { AddPokeballModifier, AddVoucherModifier, AttackTypeBoosterModifier, BaseStatModifier, BerryModifier, BoostBugSpawnModifier, BypassSpeedChanceModifier, ContactHeldItemTransferChanceModifier, CritBoosterModifier, DamageMoneyRewardModifier, DoubleBattleChanceBoosterModifier, EnemyAttackStatusEffectChanceModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, EvolutionItemModifier, EvolutionStatBoosterModifier, EvoTrackerModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, GigantamaxAccessModifier, HealingBoosterModifier, HealShopCostModifier, HiddenAbilityRateBoosterModifier, HitHealModifier, IvScannerModifier, LevelIncrementBoosterModifier, LockModifierTiersModifier, MapModifier, MegaEvolutionAccessModifier, MoneyInterestModifier, MoneyMultiplierModifier, MoneyRewardModifier, MultipleParticipantExpBonusModifier, PokemonAllMovePpRestoreModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, PokemonInstantReviveModifier, PokemonLevelIncrementModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, PokemonNatureChangeModifier, PokemonNatureWeightModifier, PokemonPpRestoreModifier, PokemonPpUpModifier, PokemonStatusHealModifier, PreserveBerryModifier, RememberMoveModifier, ResetNegativeStatStageModifier, ShinyRateBoosterModifier, SpeciesCritBoosterModifier, SpeciesStatBoosterModifier, SurviveDamageModifier, SwitchEffectTransferModifier, TempCritBoosterModifier, TempStatStageBoosterModifier, TerastallizeAccessModifier, TerastallizeModifier, TmModifier, TurnHealModifier, TurnHeldItemTransferModifier, TurnStatusEffectModifier, type EnemyPersistentModifier, type Modifier, type PersistentModifier, TempExtraModifierModifier, CriticalCatchChanceBoosterModifier } from "#app/modifier/modifier";
|
||||
import { AddPokeballModifier, AddVoucherModifier, AttackTypeBoosterModifier, BaseStatModifier, BerryModifier, BoostBugSpawnModifier, BypassSpeedChanceModifier, ContactHeldItemTransferChanceModifier, CritBoosterModifier, DamageMoneyRewardModifier, DoubleBattleChanceBoosterModifier, EnemyAttackStatusEffectChanceModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, EvolutionItemModifier, EvolutionStatBoosterModifier, EvoTrackerModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, GigantamaxAccessModifier, HealingBoosterModifier, HealShopCostModifier, HiddenAbilityRateBoosterModifier, HitHealModifier, IvScannerModifier, LevelIncrementBoosterModifier, LockModifierTiersModifier, MapModifier, MegaEvolutionAccessModifier, MoneyInterestModifier, MoneyMultiplierModifier, MoneyRewardModifier, MultipleParticipantExpBonusModifier, PokemonAllMovePpRestoreModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, PokemonInstantReviveModifier, PokemonLevelIncrementModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, PokemonNatureChangeModifier, PokemonNatureWeightModifier, PokemonPpRestoreModifier, PokemonPpUpModifier, PokemonStatusHealModifier, PreserveBerryModifier, RememberMoveModifier, ResetNegativeStatStageModifier, ShinyRateBoosterModifier, SpeciesCritBoosterModifier, SpeciesStatBoosterModifier, SurviveDamageModifier, SwitchEffectTransferModifier, TempCritBoosterModifier, TempStatStageBoosterModifier, TerastallizeAccessModifier, TerrastalizeModifier, TmModifier, TurnHealModifier, TurnHeldItemTransferModifier, TurnStatusEffectModifier, type EnemyPersistentModifier, type Modifier, type PersistentModifier, TempExtraModifierModifier, CriticalCatchChanceBoosterModifier } from "#app/modifier/modifier";
|
||||
import { ModifierTier } from "#app/modifier/modifier-tier";
|
||||
import Overrides from "#app/overrides";
|
||||
import { Unlockables } from "#app/system/unlockables";
|
||||
@ -19,7 +19,7 @@ import { getVoucherTypeIcon, getVoucherTypeName, VoucherType } from "#app/system
|
||||
import type { PokemonMoveSelectFilter, PokemonSelectFilter } from "#app/ui/party-ui-handler";
|
||||
import PartyUiHandler from "#app/ui/party-ui-handler";
|
||||
import { getModifierTierTextTint } from "#app/ui/text";
|
||||
import { formatMoney, getEnumKeys, getEnumValues, isNullOrUndefined, NumberHolder, padInt, randSeedInt, randSeedItem } from "#app/utils";
|
||||
import { formatMoney, getEnumKeys, getEnumValues, isNullOrUndefined, NumberHolder, padInt, randSeedInt } from "#app/utils";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
@ -275,6 +275,36 @@ export class PokemonHeldItemModifierType extends PokemonModifierType {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class TerastallizeModifierType extends PokemonModifierType {
|
||||
private teraType: Type;
|
||||
|
||||
constructor(teraType: Type) {
|
||||
super("", `${Type[teraType].toLowerCase()}_tera_shard`, (type, args) => new TerrastalizeModifier(type as TerastallizeModifierType, (args[0] as Pokemon).id, teraType),
|
||||
(pokemon: PlayerPokemon) => {
|
||||
if ([ pokemon.species.speciesId, pokemon.fusionSpecies?.speciesId ].filter(s => s === Species.TERAPAGOS || s === Species.OGERPON || s === Species.SHEDINJA).length > 0) {
|
||||
return PartyUiHandler.NoEffectMessage;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
"tera_shard");
|
||||
|
||||
this.teraType = teraType;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("modifierType:ModifierType.TerastallizeModifierType.name", { teraType: i18next.t(`pokemonInfo:Type.${Type[this.teraType]}`) });
|
||||
}
|
||||
|
||||
getDescription(): string {
|
||||
return i18next.t("modifierType:ModifierType.TerastallizeModifierType.description", { teraType: i18next.t(`pokemonInfo:Type.${Type[this.teraType]}`) });
|
||||
}
|
||||
|
||||
getPregenArgs(): any[] {
|
||||
return [ this.teraType ];
|
||||
}
|
||||
}
|
||||
|
||||
export class PokemonHpRestoreModifierType extends PokemonModifierType {
|
||||
protected restorePoints: number;
|
||||
protected restorePercent: number;
|
||||
@ -1156,11 +1186,11 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
|
||||
if (p.species.speciesId === Species.NECROZMA) {
|
||||
// technically we could use a simplified version and check for formChanges.length > 3, but in case any code changes later, this might break...
|
||||
|
||||
let foundULTRA_Z = false,
|
||||
foundN_LUNA = false,
|
||||
foundN_SOLAR = false;
|
||||
formChangeItemTriggers.forEach((fc, _i) => {
|
||||
console.log("Checking ", fc.item);
|
||||
switch (fc.item) {
|
||||
case FormChangeItem.ULTRANECROZIUM_Z:
|
||||
foundULTRA_Z = true;
|
||||
@ -1176,6 +1206,8 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
if (foundULTRA_Z && foundN_LUNA && foundN_SOLAR) {
|
||||
// all three items are present -> user hasn't acquired any of the N_*ARIZERs -> block ULTRANECROZIUM_Z acquisition.
|
||||
formChangeItemTriggers = formChangeItemTriggers.filter(fc => fc.item !== FormChangeItem.ULTRANECROZIUM_Z);
|
||||
} else {
|
||||
console.log("DID NOT FIND ");
|
||||
}
|
||||
}
|
||||
return formChangeItemTriggers;
|
||||
@ -1192,28 +1224,6 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
export class TerastallizeModifierType extends PokemonHeldItemModifierType implements GeneratedPersistentModifierType {
|
||||
private teraType: Type;
|
||||
|
||||
constructor(teraType: Type) {
|
||||
super("", `${Type[teraType].toLowerCase()}_tera_shard`, (type, args) => new TerastallizeModifier(type as TerastallizeModifierType, (args[0] as Pokemon).id, teraType), "tera_shard");
|
||||
|
||||
this.teraType = teraType;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return i18next.t("modifierType:ModifierType.TerastallizeModifierType.name", { teraType: i18next.t(`pokemonInfo:Type.${Type[this.teraType]}`) });
|
||||
}
|
||||
|
||||
getDescription(): string {
|
||||
return i18next.t("modifierType:ModifierType.TerastallizeModifierType.description", { teraType: i18next.t(`pokemonInfo:Type.${Type[this.teraType]}`) });
|
||||
}
|
||||
|
||||
getPregenArgs(): any[] {
|
||||
return [ this.teraType ];
|
||||
}
|
||||
}
|
||||
|
||||
export class ContactHeldItemTransferChanceModifierType extends PokemonHeldItemModifierType {
|
||||
private chancePercent: number;
|
||||
|
||||
@ -1469,14 +1479,21 @@ export const modifierTypes = {
|
||||
if (!globalScene.getModifiers(TerastallizeAccessModifier).length) {
|
||||
return null;
|
||||
}
|
||||
let type: Type;
|
||||
if (!randSeedInt(3)) {
|
||||
const partyMemberTypes = party.map(p => p.getTypes(false, false, true)).flat();
|
||||
type = randSeedItem(partyMemberTypes);
|
||||
} else {
|
||||
type = randSeedInt(64) ? randSeedInt(18) as Type : Type.STELLAR;
|
||||
const teraTypes: Type[] = [];
|
||||
party.forEach(p => {
|
||||
if (!(p.hasSpecies(Species.TERAPAGOS) || p.hasSpecies(Species.OGERPON) || p.hasSpecies(Species.SHEDINJA))) {
|
||||
teraTypes.push(p.teraType);
|
||||
}
|
||||
});
|
||||
let excludedType = Type.UNKNOWN;
|
||||
if (teraTypes.length > 0 && teraTypes.filter(t => t === teraTypes[0]).length === teraTypes.length) {
|
||||
excludedType = teraTypes[0];
|
||||
}
|
||||
return new TerastallizeModifierType(type);
|
||||
let shardType = randSeedInt(64) ? randSeedInt(18) as Type : Type.STELLAR;
|
||||
while (shardType === excludedType) {
|
||||
shardType = randSeedInt(64) ? randSeedInt(18) as Type : Type.STELLAR;
|
||||
}
|
||||
return new TerastallizeModifierType(shardType);
|
||||
}),
|
||||
|
||||
BERRY: () => new ModifierTypeGenerator((_party: Pokemon[], pregenArgs?: any[]) => {
|
||||
@ -1719,7 +1736,7 @@ const modifierPool: ModifierPool = {
|
||||
return Math.min(Math.ceil(highestPartyLevel / 20), 4);
|
||||
}, 4),
|
||||
new WeightedModifierType(modifierTypes.BASE_STAT_BOOSTER, 3),
|
||||
new WeightedModifierType(modifierTypes.TERA_SHARD, 1),
|
||||
new WeightedModifierType(modifierTypes.TERA_SHARD, (party: Pokemon[]) => party.filter(p => !(p.hasSpecies(Species.TERAPAGOS) || p.hasSpecies(Species.OGERPON) || p.hasSpecies(Species.SHEDINJA))).length > 0 ? 1 : 0),
|
||||
new WeightedModifierType(modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => {
|
||||
if (party.filter(p => !p.fusionSpecies).length > 1) {
|
||||
if (globalScene.gameMode.isSplicedOnly) {
|
||||
@ -1842,7 +1859,7 @@ const modifierPool: ModifierPool = {
|
||||
new WeightedModifierType(modifierTypes.IV_SCANNER, skipInLastClassicWaveOrDefault(4)),
|
||||
new WeightedModifierType(modifierTypes.EXP_CHARM, skipInLastClassicWaveOrDefault(8)),
|
||||
new WeightedModifierType(modifierTypes.EXP_SHARE, skipInLastClassicWaveOrDefault(10)),
|
||||
new WeightedModifierType(modifierTypes.TERA_ORB, () => Math.min(Math.max(Math.floor(globalScene.currentBattle.waveIndex / 50) * 2, 1), 4), 4),
|
||||
new WeightedModifierType(modifierTypes.TERA_ORB, () => !globalScene.gameMode.isClassic ? Math.min(Math.max(Math.floor(globalScene.currentBattle.waveIndex / 50) * 2, 1), 4) : 0, 4),
|
||||
new WeightedModifierType(modifierTypes.QUICK_CLAW, 3),
|
||||
new WeightedModifierType(modifierTypes.WIDE_LENS, 7),
|
||||
].map(m => {
|
||||
|
@ -3,16 +3,16 @@ import { getBerryEffectFunc, getBerryPredicate } from "#app/data/berry";
|
||||
import { getLevelTotalExp } from "#app/data/exp";
|
||||
import { allMoves } from "#app/data/move";
|
||||
import { MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball";
|
||||
import { type FormChangeItem, SpeciesFormChangeItemTrigger, SpeciesFormChangeLapseTeraTrigger, SpeciesFormChangeTeraTrigger } from "#app/data/pokemon-forms";
|
||||
import { type FormChangeItem, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms";
|
||||
import { getStatusEffectHealText } from "#app/data/status-effect";
|
||||
import Pokemon, { type PlayerPokemon } from "#app/field/pokemon";
|
||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||
import Pokemon from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import Overrides from "#app/overrides";
|
||||
import { EvolutionPhase } from "#app/phases/evolution-phase";
|
||||
import { LearnMovePhase, LearnMoveType } from "#app/phases/learn-move-phase";
|
||||
import { LevelUpPhase } from "#app/phases/level-up-phase";
|
||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||
import { achvs } from "#app/system/achv";
|
||||
import type { VoucherType } from "#app/system/voucher";
|
||||
import { Command } from "#app/ui/command-ui-handler";
|
||||
import { addTextObject, TextStyle } from "#app/ui/text";
|
||||
@ -25,7 +25,7 @@ import type { PokeballType } from "#enums/pokeball";
|
||||
import { Species } from "#enums/species";
|
||||
import { type PermanentStat, type TempBattleStat, BATTLE_STATS, Stat, TEMP_BATTLE_STATS } from "#enums/stat";
|
||||
import { StatusEffect } from "#enums/status-effect";
|
||||
import { Type } from "#enums/type";
|
||||
import type { Type } from "#enums/type";
|
||||
import i18next from "i18next";
|
||||
import { type DoubleBattleChanceBoosterModifierType, type EvolutionItemModifierType, type FormChangeItemModifierType, type ModifierOverride, type ModifierType, type PokemonBaseStatTotalModifierType, type PokemonExpBoosterModifierType, type PokemonFriendshipBoosterModifierType, type PokemonMoveAccuracyBoosterModifierType, type PokemonMultiHitModifierType, type TerastallizeModifierType, type TmModifierType, getModifierType, ModifierPoolType, ModifierTypeGenerator, modifierTypes, PokemonHeldItemModifierType } from "./modifier-type";
|
||||
import { Color, ShadowColor } from "#enums/color";
|
||||
@ -786,72 +786,6 @@ export abstract class LapsingPokemonHeldItemModifier extends PokemonHeldItemModi
|
||||
}
|
||||
}
|
||||
|
||||
export class TerastallizeModifier extends LapsingPokemonHeldItemModifier {
|
||||
public override type: TerastallizeModifierType;
|
||||
public teraType: Type;
|
||||
public isTransferable: boolean = false;
|
||||
|
||||
constructor(type: TerastallizeModifierType, pokemonId: number, teraType: Type, battlesLeft?: number, stackCount?: number) {
|
||||
super(type, pokemonId, battlesLeft || 10, stackCount);
|
||||
|
||||
this.teraType = teraType;
|
||||
}
|
||||
|
||||
matchType(modifier: Modifier): boolean {
|
||||
if (modifier instanceof TerastallizeModifier && modifier.teraType === this.teraType) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
clone(): TerastallizeModifier {
|
||||
return new TerastallizeModifier(this.type, this.pokemonId, this.teraType, this.battlesLeft, this.stackCount);
|
||||
}
|
||||
|
||||
getArgs(): any[] {
|
||||
return [ this.pokemonId, this.teraType, this.battlesLeft ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the {@linkcode TerastallizeModifier} to the specified {@linkcode Pokemon}.
|
||||
* @param pokemon the {@linkcode Pokemon} to be terastallized
|
||||
* @returns always `true`
|
||||
*/
|
||||
override apply(pokemon: Pokemon): boolean {
|
||||
if (pokemon.isPlayer()) {
|
||||
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeTeraTrigger);
|
||||
globalScene.validateAchv(achvs.TERASTALLIZE);
|
||||
if (this.teraType === Type.STELLAR) {
|
||||
globalScene.validateAchv(achvs.STELLAR_TERASTALLIZE);
|
||||
}
|
||||
}
|
||||
pokemon.updateSpritePipelineData();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers {@linkcode LapsingPokemonHeldItemModifier.lapse} and if it returns `0` a form change is triggered.
|
||||
* @param pokemon THe {@linkcode Pokemon} to be terastallized
|
||||
* @returns the result of {@linkcode LapsingPokemonHeldItemModifier.lapse}
|
||||
*/
|
||||
public override lapse(pokemon: Pokemon): boolean {
|
||||
const ret = super.lapse(pokemon);
|
||||
if (!ret) {
|
||||
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeLapseTeraTrigger);
|
||||
pokemon.updateSpritePipelineData();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
getScoreMultiplier(): number {
|
||||
return 1.25;
|
||||
}
|
||||
|
||||
getMaxHeldItemCount(pokemon: Pokemon): number {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifier used for held items, specifically vitamins like Carbos, Hp Up, etc., that
|
||||
* increase the value of a given {@linkcode PermanentStat}.
|
||||
@ -2022,6 +1956,36 @@ export abstract class ConsumablePokemonModifier extends ConsumableModifier {
|
||||
}
|
||||
}
|
||||
|
||||
export class TerrastalizeModifier extends ConsumablePokemonModifier {
|
||||
public override type: TerastallizeModifierType;
|
||||
public teraType: Type;
|
||||
|
||||
constructor(type: TerastallizeModifierType, pokemonId: number, teraType: Type) {
|
||||
super(type, pokemonId);
|
||||
|
||||
this.teraType = teraType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if {@linkcode TerrastalizeModifier} should be applied
|
||||
* @param playerPokemon The {@linkcode PlayerPokemon} that consumes the item
|
||||
* @returns `true` if the {@linkcode TerrastalizeModifier} should be applied
|
||||
*/
|
||||
override shouldApply(playerPokemon?: PlayerPokemon): boolean {
|
||||
return super.shouldApply(playerPokemon) && [ playerPokemon?.species.speciesId, playerPokemon?.fusionSpecies?.speciesId ].filter(s => s === Species.TERAPAGOS || s === Species.OGERPON || s === Species.SHEDINJA).length === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies {@linkcode TerrastalizeModifier}
|
||||
* @param pokemon The {@linkcode PlayerPokemon} that consumes the item
|
||||
* @returns `true` if hp was restored
|
||||
*/
|
||||
override apply(pokemon: Pokemon): boolean {
|
||||
pokemon.teraType = this.teraType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class PokemonHpRestoreModifier extends ConsumablePokemonModifier {
|
||||
private restorePoints: number;
|
||||
private restorePercent: number;
|
||||
|
@ -118,6 +118,7 @@ export class CommandPhase extends FieldPhase {
|
||||
let success: boolean = false;
|
||||
|
||||
switch (command) {
|
||||
case Command.TERA:
|
||||
case Command.FIGHT:
|
||||
let useStruggle = false;
|
||||
const turnMove: TurnMove | undefined = (args.length === 2 ? (args[1] as TurnMove) : undefined);
|
||||
@ -137,6 +138,7 @@ export class CommandPhase extends FieldPhase {
|
||||
}
|
||||
|
||||
const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: { move: moveId, targets: [], ignorePP: args[0] }, args: args };
|
||||
const preTurnCommand: TurnCommand = { command: command, targets: [ this.fieldIndex ], skip: command === Command.FIGHT };
|
||||
const moveTargets: MoveTargetSet = turnMove === undefined ? getMoveTargets(playerPokemon, moveId) : { targets: turnMove.targets, multiple: turnMove.targets.length > 1 };
|
||||
if (!moveId) {
|
||||
turnCommand.targets = [ this.fieldIndex ];
|
||||
@ -152,6 +154,7 @@ export class CommandPhase extends FieldPhase {
|
||||
} else {
|
||||
globalScene.unshiftPhase(new SelectTargetPhase(this.fieldIndex));
|
||||
}
|
||||
globalScene.currentBattle.preTurnCommands[this.fieldIndex] = preTurnCommand;
|
||||
globalScene.currentBattle.turnCommands[this.fieldIndex] = turnCommand;
|
||||
success = true;
|
||||
} else if (cursor < playerPokemon.getMoveset().length) {
|
||||
|
@ -81,6 +81,10 @@ export class EnemyCommandPhase extends FieldPhase {
|
||||
/** Select a move to use (and a target to use it against, if applicable) */
|
||||
const nextMove = enemyPokemon.getNextMove();
|
||||
|
||||
if (trainer && trainer.shouldTera(enemyPokemon)) {
|
||||
globalScene.currentBattle.preTurnCommands[this.fieldIndex + BattlerIndex.ENEMY] = { command: Command.TERA };
|
||||
}
|
||||
|
||||
globalScene.currentBattle.turnCommands[this.fieldIndex + BattlerIndex.ENEMY] =
|
||||
{ command: Command.FIGHT, move: nextMove, skip: this.skipTurn };
|
||||
|
||||
|
@ -116,7 +116,7 @@ export class EvolutionPhase extends Phase {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
|
||||
sprite.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(this.pokemon.getTeraType()) });
|
||||
sprite.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(this.pokemon.getTeraType()), isTerastallized: this.pokemon.isTerastallized });
|
||||
sprite.setPipelineData("ignoreTimeTint", true);
|
||||
sprite.setPipelineData("spriteKey", this.pokemon.getSpriteKey());
|
||||
sprite.setPipelineData("shiny", this.pokemon.shiny);
|
||||
|
@ -108,6 +108,8 @@ export class FaintPhase extends PokemonPhase {
|
||||
globalScene.queueMessage(i18next.t("battle:fainted", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), null, true);
|
||||
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true);
|
||||
|
||||
pokemon.resetTera();
|
||||
|
||||
if (pokemon.turnData?.attacksReceived?.length) {
|
||||
const lastAttack = pokemon.turnData.attacksReceived[0];
|
||||
applyPostFaintAbAttrs(PostFaintAbAttr, pokemon, globalScene.getPokemonById(lastAttack.sourceId)!, new PokemonMove(lastAttack.move).getMove(), lastAttack.result); // TODO: is this bang correct?
|
||||
|
@ -15,7 +15,7 @@ export class MoneyRewardPhase extends BattlePhase {
|
||||
}
|
||||
|
||||
start() {
|
||||
const moneyAmount = new Utils.IntegerHolder(globalScene.getWaveMoneyAmount(this.moneyMultiplier));
|
||||
const moneyAmount = new Utils.NumberHolder(globalScene.getWaveMoneyAmount(this.moneyMultiplier));
|
||||
|
||||
globalScene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount);
|
||||
|
||||
|
@ -450,6 +450,12 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
target.lapseTag(BattlerTagType.SUBSTITUTE);
|
||||
}
|
||||
});
|
||||
|
||||
const moveType = user.getMoveType(move, true);
|
||||
if (move.category !== MoveCategory.STATUS && !user.stellarTypesBoosted.includes(moveType)) {
|
||||
user.stellarTypesBoosted.push(moveType);
|
||||
}
|
||||
|
||||
this.end();
|
||||
});
|
||||
});
|
||||
|
@ -354,7 +354,7 @@ export class MovePhase extends BattlePhase {
|
||||
if (failureMessage) {
|
||||
failedText = failureMessage;
|
||||
} else if (failedDueToTerrain) {
|
||||
failedText = getTerrainBlockMessage(this.pokemon, globalScene.arena.getTerrainType());
|
||||
failedText = getTerrainBlockMessage(targets[0], globalScene.arena.getTerrainType());
|
||||
}
|
||||
|
||||
this.showFailedText(failedText);
|
||||
|
@ -36,5 +36,6 @@ export class PartyHealPhase extends BattlePhase {
|
||||
globalScene.ui.fadeIn(500).then(() => this.end());
|
||||
});
|
||||
});
|
||||
globalScene.arena.playerTerasUsed = 0;
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ export class PokemonHealPhase extends CommonAnimPhase {
|
||||
this.message = null;
|
||||
return super.end();
|
||||
} else if (healOrDamage) {
|
||||
const hpRestoreMultiplier = new Utils.IntegerHolder(1);
|
||||
const hpRestoreMultiplier = new Utils.NumberHolder(1);
|
||||
if (!this.revive) {
|
||||
globalScene.applyModifiers(HealingBoosterModifier, this.player, hpRestoreMultiplier);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { SemiInvulnerableTag } from "#app/data/battler-tags";
|
||||
import type { SpeciesFormChange } from "#app/data/pokemon-forms";
|
||||
import { getSpeciesFormChangeMessage } from "#app/data/pokemon-forms";
|
||||
import { getSpeciesFormChangeMessage, SpeciesFormChangeTeraTrigger } from "#app/data/pokemon-forms";
|
||||
import { getTypeRgb } from "#app/data/type";
|
||||
import { BattleSpec } from "#app/enums/battle-spec";
|
||||
import { BattlerTagType } from "#app/enums/battler-tag-type";
|
||||
@ -11,6 +11,7 @@ import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
import { MovePhase } from "./move-phase";
|
||||
import { PokemonHealPhase } from "./pokemon-heal-phase";
|
||||
import { applyAbAttrs, PostTeraFormChangeStatChangeAbAttr } from "#app/data/ability";
|
||||
|
||||
export class QuietFormChangePhase extends BattlePhase {
|
||||
protected pokemon: Pokemon;
|
||||
@ -51,7 +52,7 @@ export class QuietFormChangePhase extends BattlePhase {
|
||||
} catch (err: unknown) {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
sprite.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(this.pokemon.getTeraType()) });
|
||||
sprite.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: false, teraColor: getTypeRgb(this.pokemon.getTeraType()), isTerastallized: this.pokemon.isTerastallized });
|
||||
[ "spriteColors", "fusionSpriteColors" ].map(k => {
|
||||
if (this.pokemon.summonData?.speciesForm) {
|
||||
k += "Base";
|
||||
@ -145,6 +146,9 @@ export class QuietFormChangePhase extends BattlePhase {
|
||||
movePhase.cancel();
|
||||
}
|
||||
}
|
||||
if (this.formChange.trigger instanceof SpeciesFormChangeTeraTrigger) {
|
||||
applyAbAttrs(PostTeraFormChangeStatChangeAbAttr, this.pokemon, null);
|
||||
}
|
||||
|
||||
super.end();
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ export class SelectModifierPhase extends BattlePhase {
|
||||
if (!this.isCopy) {
|
||||
regenerateModifierPoolThresholds(party, this.getPoolType(), this.rerollCount);
|
||||
}
|
||||
const modifierCount = new Utils.IntegerHolder(3);
|
||||
const modifierCount = new Utils.NumberHolder(3);
|
||||
if (this.isPlayer()) {
|
||||
globalScene.applyModifiers(ExtraModifierModifier, true, modifierCount);
|
||||
globalScene.applyModifiers(TempExtraModifierModifier, true, modifierCount);
|
||||
|
51
src/phases/tera-phase.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
import i18next from "i18next";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { Type } from "#app/enums/type";
|
||||
import { achvs } from "#app/system/achv";
|
||||
import { SpeciesFormChangeTeraTrigger } from "#app/data/pokemon-forms";
|
||||
import { CommonAnim, CommonBattleAnim } from "#app/data/battle-anims";
|
||||
|
||||
export class TeraPhase extends BattlePhase {
|
||||
public pokemon: Pokemon;
|
||||
|
||||
constructor(pokemon: Pokemon) {
|
||||
super();
|
||||
|
||||
this.pokemon = pokemon;
|
||||
}
|
||||
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
console.log(this.pokemon.name, "terastallized to", Type[this.pokemon.teraType].toString());
|
||||
|
||||
globalScene.queueMessage(i18next.t("battle:pokemonTerastallized", { pokemonNameWithAffix: getPokemonNameWithAffix(this.pokemon), type: i18next.t(`pokemonInfo:Type.${Type[this.pokemon.teraType]}`) }));
|
||||
new CommonBattleAnim(CommonAnim.TERASTALLIZE, this.pokemon).play(false, () => {
|
||||
this.end();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
end() {
|
||||
this.pokemon.isTerastallized = true;
|
||||
this.pokemon.updateSpritePipelineData();
|
||||
|
||||
if (this.pokemon.isPlayer()) {
|
||||
globalScene.arena.playerTerasUsed += 1;
|
||||
}
|
||||
|
||||
globalScene.triggerPokemonFormChange(this.pokemon, SpeciesFormChangeTeraTrigger);
|
||||
|
||||
if (this.pokemon.isPlayer()) {
|
||||
globalScene.validateAchv(achvs.TERASTALLIZE);
|
||||
if (this.pokemon.teraType === Type.STELLAR) {
|
||||
globalScene.validateAchv(achvs.STELLAR_TERASTALLIZE);
|
||||
}
|
||||
}
|
||||
|
||||
super.end();
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ import { BattlerIndex } from "#app/battle";
|
||||
import { TrickRoomTag } from "#app/data/arena-tag";
|
||||
import { SwitchType } from "#enums/switch-type";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { TeraPhase } from "./tera-phase";
|
||||
|
||||
export class TurnStartPhase extends FieldPhase {
|
||||
constructor() {
|
||||
@ -139,6 +140,20 @@ export class TurnStartPhase extends FieldPhase {
|
||||
|
||||
let orderIndex = 0;
|
||||
|
||||
for (const o of this.getSpeedOrder()) {
|
||||
const pokemon = field[o];
|
||||
const preTurnCommand = globalScene.currentBattle.preTurnCommands[o];
|
||||
|
||||
if (preTurnCommand?.skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (preTurnCommand?.command) {
|
||||
case Command.TERA:
|
||||
globalScene.pushPhase(new TeraPhase(pokemon));
|
||||
}
|
||||
}
|
||||
|
||||
for (const o of moveOrder) {
|
||||
|
||||
const pokemon = field[o];
|
||||
|
@ -351,7 +351,7 @@ export default class SpritePipeline extends FieldSpritePipeline {
|
||||
|
||||
const data = sprite.pipelineData;
|
||||
const tone = data["tone"] as number[];
|
||||
const teraColor = data["teraColor"] as number[] ?? [ 0, 0, 0 ];
|
||||
const teraColor = (data["isTerastallized"] as boolean) ? (data["teraColor"] as number[] ?? [ 0, 0, 0 ]) : [ 0, 0, 0 ];
|
||||
const hasShadow = data["hasShadow"] as boolean;
|
||||
const yShadowOffset = data["yShadowOffset"] as number;
|
||||
const ignoreFieldPos = data["ignoreFieldPos"] as boolean;
|
||||
|
@ -10,12 +10,14 @@ export default class ArenaData {
|
||||
public weather: Weather | null;
|
||||
public terrain: Terrain | null;
|
||||
public tags: ArenaTag[];
|
||||
public playerTerasUsed: number;
|
||||
|
||||
constructor(source: Arena | any) {
|
||||
const sourceArena = source instanceof Arena ? source as Arena : null;
|
||||
this.biome = sourceArena ? sourceArena.biomeType : source.biome;
|
||||
this.weather = sourceArena ? sourceArena.weather : source.weather ? new Weather(source.weather.weatherType, source.weather.turnsLeft) : null;
|
||||
this.terrain = sourceArena ? sourceArena.terrain : source.terrain ? new Terrain(source.terrain.terrainType, source.terrain.turnsLeft) : null;
|
||||
this.playerTerasUsed = (sourceArena ? sourceArena.playerTerasUsed : source.playerTerasUsed) ?? 0;
|
||||
this.tags = [];
|
||||
|
||||
if (source.tags) {
|
||||
|
@ -1087,6 +1087,8 @@ export class GameData {
|
||||
globalScene.arena.terrain = sessionData.arena.terrain;
|
||||
globalScene.arena.eventTarget.dispatchEvent(new TerrainChangedEvent(TerrainType.NONE, globalScene.arena.terrain?.terrainType!, globalScene.arena.terrain?.turnsLeft!)); // TODO: is this bang correct?
|
||||
|
||||
globalScene.arena.playerTerasUsed = sessionData.arena.playerTerasUsed;
|
||||
|
||||
globalScene.arena.tags = sessionData.arena.tags;
|
||||
if (globalScene.arena.tags) {
|
||||
for (const tag of globalScene.arena.tags) {
|
||||
|
@ -13,6 +13,7 @@ import type { Biome } from "#enums/biome";
|
||||
import { Moves } from "#enums/moves";
|
||||
import type { Species } from "#enums/species";
|
||||
import { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import type { Type } from "#app/enums/type";
|
||||
|
||||
export default class PokemonData {
|
||||
public id: number;
|
||||
@ -45,6 +46,9 @@ export default class PokemonData {
|
||||
public pokerus: boolean;
|
||||
public usedTMs: Moves[];
|
||||
public evoCounter: number;
|
||||
public teraType: Type;
|
||||
public isTerastallized: boolean;
|
||||
public stellarTypesBoosted: Type[];
|
||||
|
||||
public fusionSpecies: Species;
|
||||
public fusionFormIndex: number;
|
||||
@ -53,6 +57,7 @@ export default class PokemonData {
|
||||
public fusionVariant: Variant;
|
||||
public fusionGender: Gender;
|
||||
public fusionLuck: number;
|
||||
public fusionTeraType: Type;
|
||||
|
||||
public boss: boolean;
|
||||
public bossSegments?: number;
|
||||
@ -103,6 +108,9 @@ export default class PokemonData {
|
||||
this.evoCounter = source.evoCounter ?? 0;
|
||||
}
|
||||
this.pokerus = !!source.pokerus;
|
||||
this.teraType = source.teraType as Type;
|
||||
this.isTerastallized = source.isTerastallized || false;
|
||||
this.stellarTypesBoosted = source.stellarTypesBoosted || [];
|
||||
|
||||
this.fusionSpecies = sourcePokemon ? sourcePokemon.fusionSpecies?.speciesId : source.fusionSpecies;
|
||||
this.fusionFormIndex = source.fusionFormIndex;
|
||||
@ -112,6 +120,7 @@ export default class PokemonData {
|
||||
this.fusionGender = source.fusionGender;
|
||||
this.fusionLuck = source.fusionLuck !== undefined ? source.fusionLuck : (source.fusionShiny ? source.fusionVariant + 1 : 0);
|
||||
this.fusionCustomPokemonData = new CustomPokemonData(source.fusionCustomPokemonData);
|
||||
this.fusionTeraType = (source.fusionTeraType ?? 0) as Type;
|
||||
this.usedTMs = source.usedTMs ?? [];
|
||||
|
||||
this.customPokemonData = new CustomPokemonData(source.customPokemonData);
|
||||
|
@ -7,6 +7,9 @@ import * as v1_0_4 from "./versions/v1_0_4";
|
||||
// --- v1.1.0 PATCHES --- //
|
||||
import * as v1_1_0 from "./versions/v1_1_0";
|
||||
|
||||
// --- v1.7.0 PATCHES --- //
|
||||
import * as v1_7_0 from "./versions/v1_7_0";
|
||||
|
||||
const LATEST_VERSION = version.split(".").map(value => parseInt(value));
|
||||
|
||||
/**
|
||||
@ -138,6 +141,10 @@ class SessionVersionConverter extends VersionConverter {
|
||||
console.log("Applying v1.1.0 session data migration!");
|
||||
this.callMigrators(data, v1_1_0.sessionMigrators);
|
||||
}
|
||||
if (curMinor < 7) {
|
||||
console.log("Applying v1.7.0 session data migration!");
|
||||
this.callMigrators(data, v1_7_0.sessionMigrators);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Session data successfully migrated to v${version}!`);
|
||||
@ -164,6 +171,10 @@ class SystemVersionConverter extends VersionConverter {
|
||||
console.log("Applying v1.1.0 system data migraton!");
|
||||
this.callMigrators(data, v1_1_0.systemMigrators);
|
||||
}
|
||||
if (curMinor < 7) {
|
||||
console.log("Applying v1.7.0 system data migration!");
|
||||
this.callMigrators(data, v1_7_0.systemMigrators);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`System data successfully migrated to v${version}!`);
|
||||
@ -190,8 +201,12 @@ class SettingsVersionConverter extends VersionConverter {
|
||||
console.log("Applying v1.1.0 settings data migraton!");
|
||||
this.callMigrators(data, v1_1_0.settingsMigrators);
|
||||
}
|
||||
if (curMinor < 7) {
|
||||
console.log("Applying v1.7.0 settings data migration!");
|
||||
this.callMigrators(data, v1_7_0.settingsMigrators);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`System data successfully migrated to v${version}!`);
|
||||
console.log(`Settings data successfully migrated to v${version}!`);
|
||||
}
|
||||
}
|
||||
|
49
src/system/version_migration/versions/v1_7_0.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||
import type { SessionSaveData } from "#app/system/game-data";
|
||||
import * as Utils from "#app/utils";
|
||||
|
||||
export const systemMigrators = [] as const;
|
||||
|
||||
export const settingsMigrators = [] as const;
|
||||
|
||||
export const sessionMigrators = [
|
||||
function migrateTera(data: SessionSaveData) {
|
||||
for (let i = 0; i < data.modifiers.length;) {
|
||||
if (data.modifiers[i].className === "TerastallizeModifier") {
|
||||
data.party.forEach((p) => {
|
||||
if (p.id === data.modifiers[i].args[0]) {
|
||||
p.teraType = data.modifiers[i].args[1];
|
||||
}
|
||||
});
|
||||
data.modifiers.splice(i, 1);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < data.enemyModifiers.length;) {
|
||||
if (data.enemyModifiers[i].className === "TerastallizeModifier") {
|
||||
data.enemyParty.forEach((p) => {
|
||||
if (p.id === data.enemyModifiers[i].args[0]) {
|
||||
p.teraType = data.enemyModifiers[i].args[1];
|
||||
}
|
||||
});
|
||||
data.enemyModifiers.splice(i, 1);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
data.party.forEach(p => {
|
||||
if (Utils.isNullOrUndefined(p.teraType)) {
|
||||
p.teraType = getPokemonSpeciesForm(p.species, p.formIndex).type1;
|
||||
}
|
||||
});
|
||||
|
||||
data.enemyParty.forEach(p => {
|
||||
if (Utils.isNullOrUndefined(p.teraType)) {
|
||||
p.teraType = getPokemonSpeciesForm(p.species, p.formIndex).type1;
|
||||
}
|
||||
});
|
||||
}
|
||||
] as const;
|
@ -11,7 +11,7 @@ import { Species } from "#enums/species";
|
||||
import { WeatherType } from "#enums/weather-type";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest";
|
||||
|
||||
|
||||
describe("Abilities - Libero", () => {
|
||||
@ -258,7 +258,7 @@ describe("Abilities - Libero", () => {
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
expect(leadPokemon).not.toBe(undefined);
|
||||
|
||||
vi.spyOn(leadPokemon, "isTerastallized").mockReturnValue(true);
|
||||
leadPokemon.isTerastallized = true;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
@ -11,7 +11,7 @@ import { Species } from "#enums/species";
|
||||
import { WeatherType } from "#enums/weather-type";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest";
|
||||
|
||||
|
||||
describe("Abilities - Protean", () => {
|
||||
@ -258,7 +258,7 @@ describe("Abilities - Protean", () => {
|
||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||
expect(leadPokemon).not.toBe(undefined);
|
||||
|
||||
vi.spyOn(leadPokemon, "isTerastallized").mockReturnValue(true);
|
||||
leadPokemon.isTerastallized = true;
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { TurnHeldItemTransferModifier } from "#app/modifier/modifier";
|
||||
import { Achv, AchvTier, DamageAchv, HealAchv, LevelAchv, ModifierAchv, MoneyAchv, RibbonAchv, achvs } from "#app/system/achv";
|
||||
import { IntegerHolder, NumberHolder } from "#app/utils";
|
||||
import { NumberHolder } from "#app/utils";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
@ -174,7 +174,7 @@ describe("LevelAchv", () => {
|
||||
|
||||
it("should validate the achievement based on the level", () => {
|
||||
const levelAchv = new LevelAchv("", "Test Level Achievement", 100, "level_icon", 10);
|
||||
const integerHolder = new IntegerHolder(50);
|
||||
const integerHolder = new NumberHolder(50);
|
||||
|
||||
expect(levelAchv.validate([ integerHolder ])).toBe(false);
|
||||
|
||||
|
@ -150,6 +150,17 @@ describe("Spec - Pokemon", () => {
|
||||
expect(types[1]).toBe(Type.DARK);
|
||||
});
|
||||
|
||||
it("Fusing mons with two and one types", async () => {
|
||||
game.override.starterSpecies(Species.NUMEL);
|
||||
game.override.starterFusionSpecies(Species.CHARMANDER);
|
||||
await game.classicMode.startBattle();
|
||||
const pokemon = scene.getPlayerParty()[0];
|
||||
|
||||
const types = pokemon.getTypes();
|
||||
expect(types[0]).toBe(Type.FIRE);
|
||||
expect(types[1]).toBe(Type.GROUND);
|
||||
});
|
||||
|
||||
it("Fusing two mons with two types", async () => {
|
||||
game.override.starterSpecies(Species.NATU);
|
||||
game.override.starterFusionSpecies(Species.HOUNDOUR);
|
||||
|
@ -6,7 +6,6 @@ import { Abilities } from "#app/enums/abilities";
|
||||
import { Moves } from "#app/enums/moves";
|
||||
import { Species } from "#app/enums/species";
|
||||
import * as Messages from "#app/messages";
|
||||
import { TerastallizeModifier, overrideHeldItems } from "#app/modifier/modifier";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
@ -15,15 +14,14 @@ function testMoveEffectiveness(game: GameManager, move: Moves, targetSpecies: Sp
|
||||
expected: number, targetAbility: Abilities = Abilities.BALL_FETCH, teraType?: Type): void {
|
||||
// Suppress getPokemonNameWithAffix because it calls on a null battle spec
|
||||
vi.spyOn(Messages, "getPokemonNameWithAffix").mockReturnValue("");
|
||||
game.override
|
||||
.enemyAbility(targetAbility)
|
||||
.enemyHeldItems([{ name:"TERA_SHARD", type: teraType }]);
|
||||
game.override.enemyAbility(targetAbility);
|
||||
|
||||
const user = game.scene.addPlayerPokemon(getPokemonSpecies(Species.SNORLAX), 5);
|
||||
const target = game.scene.addEnemyPokemon(getPokemonSpecies(targetSpecies), 5, TrainerSlot.NONE);
|
||||
|
||||
if (teraType !== undefined) {
|
||||
overrideHeldItems(target, false);
|
||||
target.teraType = teraType;
|
||||
target.isTerastallized = true;
|
||||
}
|
||||
|
||||
expect(target.getMoveEffectiveness(user, allMoves[move])).toBe(expected);
|
||||
@ -40,7 +38,6 @@ describe("Moves - Type Effectiveness", () => {
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
game = new GameManager(phaserGame);
|
||||
TerastallizeModifier.prototype.apply = (args) => true;
|
||||
|
||||
game.override.ability(Abilities.BALL_FETCH);
|
||||
});
|
||||
|
@ -117,11 +117,12 @@ describe("Moves - Freeze-Dry", () => {
|
||||
});
|
||||
|
||||
it("should deal 2x damage to steel type terastallized into water", async () => {
|
||||
game.override.enemySpecies(Species.SKARMORY)
|
||||
.enemyHeldItems([{ name: "TERA_SHARD", type: Type.WATER }]);
|
||||
game.override.enemySpecies(Species.SKARMORY);
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
enemy.teraType = Type.WATER;
|
||||
enemy.isTerastallized = true;
|
||||
vi.spyOn(enemy, "getMoveEffectiveness");
|
||||
|
||||
game.move.select(Moves.FREEZE_DRY);
|
||||
@ -132,11 +133,12 @@ describe("Moves - Freeze-Dry", () => {
|
||||
});
|
||||
|
||||
it("should deal 0.5x damage to water type terastallized into fire", async () => {
|
||||
game.override.enemySpecies(Species.PELIPPER)
|
||||
.enemyHeldItems([{ name: "TERA_SHARD", type: Type.FIRE }]);
|
||||
game.override.enemySpecies(Species.PELIPPER);
|
||||
await game.classicMode.startBattle();
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
enemy.teraType = Type.FIRE;
|
||||
enemy.isTerastallized = true;
|
||||
vi.spyOn(enemy, "getMoveEffectiveness");
|
||||
|
||||
game.move.select(Moves.FREEZE_DRY);
|
||||
|
@ -83,10 +83,12 @@ describe("Moves - Tar Shot", () => {
|
||||
});
|
||||
|
||||
it("does not double the effectiveness of Fire-type moves against a Pokémon that is Terastallized", async () => {
|
||||
game.override.enemyHeldItems([{ name: "TERA_SHARD", type: Type.GRASS }]).enemySpecies(Species.SPRIGATITO);
|
||||
game.override.enemySpecies(Species.SPRIGATITO);
|
||||
await game.classicMode.startBattle([ Species.PIKACHU ]);
|
||||
|
||||
const enemy = game.scene.getEnemyPokemon()!;
|
||||
enemy.teraType = Type.GRASS;
|
||||
enemy.isTerastallized = true;
|
||||
|
||||
vi.spyOn(enemy, "getMoveEffectiveness");
|
||||
|
||||
@ -119,7 +121,8 @@ describe("Moves - Tar Shot", () => {
|
||||
|
||||
await game.toNextTurn();
|
||||
|
||||
game.override.enemyHeldItems([{ name: "TERA_SHARD", type: Type.GRASS }]);
|
||||
enemy.teraType = Type.GRASS;
|
||||
enemy.isTerastallized = true;
|
||||
|
||||
game.move.select(Moves.FIRE_PUNCH);
|
||||
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
|
||||
|
@ -35,7 +35,6 @@ describe("Moves - Tera Blast", () => {
|
||||
.starterSpecies(Species.FEEBAS)
|
||||
.moveset([ Moves.TERA_BLAST ])
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.startingHeldItems([{ name: "TERA_SHARD", type: Type.FIRE }])
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.enemyMoveset(Moves.SPLASH)
|
||||
.enemyAbility(Abilities.STURDY)
|
||||
@ -45,13 +44,15 @@ describe("Moves - Tera Blast", () => {
|
||||
});
|
||||
|
||||
it("changes type to match user's tera type", async () => {
|
||||
game.override
|
||||
.enemySpecies(Species.FURRET)
|
||||
.startingHeldItems([{ name: "TERA_SHARD", type: Type.FIGHTING }]);
|
||||
game.override.enemySpecies(Species.FURRET);
|
||||
await game.startBattle();
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemyPokemon, "apply");
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
playerPokemon.teraType = Type.FIGHTING;
|
||||
playerPokemon.isTerastallized = true;
|
||||
|
||||
game.move.select(Moves.TERA_BLAST);
|
||||
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
@ -60,10 +61,12 @@ describe("Moves - Tera Blast", () => {
|
||||
}, 20000);
|
||||
|
||||
it("increases power if user is Stellar tera type", async () => {
|
||||
game.override.startingHeldItems([{ name: "TERA_SHARD", type: Type.STELLAR }]);
|
||||
|
||||
await game.startBattle();
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
playerPokemon.teraType = Type.STELLAR;
|
||||
playerPokemon.isTerastallized = true;
|
||||
|
||||
game.move.select(Moves.TERA_BLAST);
|
||||
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
|
||||
await game.phaseInterceptor.to("MoveEffectPhase");
|
||||
@ -72,13 +75,15 @@ describe("Moves - Tera Blast", () => {
|
||||
}, 20000);
|
||||
|
||||
it("is super effective against terastallized targets if user is Stellar tera type", async () => {
|
||||
game.override.startingHeldItems([{ name: "TERA_SHARD", type: Type.STELLAR }]);
|
||||
|
||||
await game.startBattle();
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
playerPokemon.teraType = Type.STELLAR;
|
||||
playerPokemon.isTerastallized = true;
|
||||
|
||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||
vi.spyOn(enemyPokemon, "apply");
|
||||
vi.spyOn(enemyPokemon, "isTerastallized").mockReturnValue(true);
|
||||
enemyPokemon.isTerastallized = true;
|
||||
|
||||
game.move.select(Moves.TERA_BLAST);
|
||||
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
|
||||
@ -93,6 +98,7 @@ describe("Moves - Tera Blast", () => {
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
playerPokemon.stats[Stat.ATK] = 100;
|
||||
playerPokemon.stats[Stat.SPATK] = 1;
|
||||
playerPokemon.isTerastallized = true;
|
||||
|
||||
vi.spyOn(teraBlastAttr, "apply");
|
||||
|
||||
@ -169,10 +175,11 @@ describe("Moves - Tera Blast", () => {
|
||||
|
||||
|
||||
it("causes stat drops if user is Stellar tera type", async () => {
|
||||
game.override.startingHeldItems([{ name: "TERA_SHARD", type: Type.STELLAR }]);
|
||||
await game.startBattle();
|
||||
|
||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||
playerPokemon.teraType = Type.STELLAR;
|
||||
playerPokemon.isTerastallized = true;
|
||||
|
||||
game.move.select(Moves.TERA_BLAST);
|
||||
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
|
||||
|
@ -29,8 +29,7 @@ describe("Moves - Tera Starstorm", () => {
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyMoveset(Moves.SPLASH)
|
||||
.enemyLevel(30)
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.startingHeldItems([{ name: "TERA_SHARD", type: Type.FIRE }]);
|
||||
.enemySpecies(Species.MAGIKARP);
|
||||
});
|
||||
|
||||
it("changes type to Stellar when used by Terapagos in its Stellar Form", async () => {
|
||||
@ -38,19 +37,22 @@ describe("Moves - Tera Starstorm", () => {
|
||||
await game.classicMode.startBattle([ Species.TERAPAGOS ]);
|
||||
|
||||
const terapagos = game.scene.getPlayerPokemon()!;
|
||||
terapagos.isTerastallized = true;
|
||||
|
||||
vi.spyOn(terapagos, "getMoveType");
|
||||
|
||||
game.move.select(Moves.TERA_STARSTORM);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(terapagos.isTerastallized()).toBe(true);
|
||||
expect(terapagos.getMoveType).toHaveReturnedWith(Type.STELLAR);
|
||||
});
|
||||
|
||||
it("targets both opponents in a double battle when used by Terapagos in its Stellar Form", async () => {
|
||||
await game.classicMode.startBattle([ Species.MAGIKARP, Species.TERAPAGOS ]);
|
||||
|
||||
const terapagos = game.scene.getPlayerParty()[1];
|
||||
terapagos.isTerastallized = true;
|
||||
|
||||
game.move.select(Moves.TERA_STARSTORM, 0, BattlerIndex.ENEMY);
|
||||
game.move.select(Moves.TERA_STARSTORM, 1);
|
||||
|
||||
@ -82,6 +84,8 @@ describe("Moves - Tera Starstorm", () => {
|
||||
fusionedMon.fusionGender = magikarp.gender;
|
||||
fusionedMon.fusionLuck = magikarp.luck;
|
||||
|
||||
fusionedMon.isTerastallized = true;
|
||||
|
||||
vi.spyOn(fusionedMon, "getMoveType");
|
||||
|
||||
game.move.select(Moves.TERA_STARSTORM, 0);
|
||||
@ -90,7 +94,6 @@ describe("Moves - Tera Starstorm", () => {
|
||||
|
||||
// Fusion and terastallized
|
||||
expect(fusionedMon.isFusion()).toBe(true);
|
||||
expect(fusionedMon.isTerastallized()).toBe(true);
|
||||
// Move effects should be applied
|
||||
expect(fusionedMon.getMoveType).toHaveReturnedWith(Type.STELLAR);
|
||||
expect(game.scene.getEnemyField().every(pokemon => pokemon.isFullHp())).toBe(false);
|
||||
|
@ -324,9 +324,9 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
this.lastTeraType = pokemon.getTeraType();
|
||||
|
||||
this.teraIcon.setPositionRelative(this.nameText, nameTextWidth + this.genderText.displayWidth + 1, 2);
|
||||
this.teraIcon.setVisible(this.lastTeraType !== Type.UNKNOWN);
|
||||
this.teraIcon.setVisible(pokemon.isTerastallized);
|
||||
this.teraIcon.on("pointerover", () => {
|
||||
if (this.lastTeraType !== Type.UNKNOWN) {
|
||||
if (pokemon.isTerastallized) {
|
||||
globalScene.ui.showTooltip("", i18next.t("fightUiHandler:teraHover", { type: i18next.t(`pokemonInfo:Type.${Type[this.lastTeraType]}`) }));
|
||||
}
|
||||
});
|
||||
@ -542,7 +542,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
||||
this.genderText.setPositionRelative(this.nameText, this.nameText.displayWidth, 0);
|
||||
}
|
||||
|
||||
const teraType = pokemon.getTeraType();
|
||||
const teraType = pokemon.isTerastallized ? pokemon.getTeraType() : Type.UNKNOWN;
|
||||
const teraTypeUpdated = this.lastTeraType !== teraType;
|
||||
|
||||
if (teraTypeUpdated) {
|
||||
|
@ -7,18 +7,24 @@ import { Button } from "#enums/buttons";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { CommandPhase } from "#app/phases/command-phase";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { TerastallizeAccessModifier } from "#app/modifier/modifier";
|
||||
import { Type } from "#app/enums/type";
|
||||
import { getTypeRgb } from "#app/data/type";
|
||||
|
||||
export enum Command {
|
||||
FIGHT = 0,
|
||||
BALL,
|
||||
POKEMON,
|
||||
RUN
|
||||
RUN,
|
||||
TERA
|
||||
}
|
||||
|
||||
export default class CommandUiHandler extends UiHandler {
|
||||
private commandsContainer: Phaser.GameObjects.Container;
|
||||
private cursorObj: Phaser.GameObjects.Image | null;
|
||||
|
||||
private teraButton: Phaser.GameObjects.Sprite;
|
||||
|
||||
protected fieldIndex: number = 0;
|
||||
protected cursor2: number = 0;
|
||||
|
||||
@ -40,6 +46,13 @@ export default class CommandUiHandler extends UiHandler {
|
||||
this.commandsContainer.setVisible(false);
|
||||
ui.add(this.commandsContainer);
|
||||
|
||||
this.teraButton = globalScene.add.sprite(-32, 15, "button_tera");
|
||||
this.teraButton.setName("terrastallize-button");
|
||||
this.teraButton.setScale(1.3);
|
||||
this.teraButton.setFrame("fire");
|
||||
this.teraButton.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true, teraColor: getTypeRgb(Type.FIRE), isTerastallized: false });
|
||||
this.commandsContainer.add(this.teraButton);
|
||||
|
||||
for (let c = 0; c < commands.length; c++) {
|
||||
const commandText = addTextObject(c % 2 === 0 ? 0 : 55.8, c < 2 ? 0 : 16, commands[c], TextStyle.WINDOW);
|
||||
commandText.setName(commands[c]);
|
||||
@ -62,11 +75,22 @@ export default class CommandUiHandler extends UiHandler {
|
||||
commandPhase = globalScene.getStandbyPhase() as CommandPhase;
|
||||
}
|
||||
|
||||
if (this.canTera()) {
|
||||
this.teraButton.setVisible(true);
|
||||
this.teraButton.setFrame(Type[globalScene.getField()[this.fieldIndex].getTeraType()].toLowerCase());
|
||||
} else {
|
||||
this.teraButton.setVisible(false);
|
||||
if (this.cursor === Command.TERA) {
|
||||
this.setCursor(Command.FIGHT);
|
||||
}
|
||||
}
|
||||
this.toggleTeraButton();
|
||||
|
||||
const messageHandler = this.getUi().getMessageHandler();
|
||||
messageHandler.bg.setVisible(true);
|
||||
messageHandler.commandWindow.setVisible(true);
|
||||
messageHandler.movesWindowContainer.setVisible(false);
|
||||
messageHandler.message.setWordWrapWidth(1110);
|
||||
messageHandler.message.setWordWrapWidth(this.canTera() ? 910 : 1110);
|
||||
messageHandler.showText(i18next.t("commandUiHandler:actionMessage", { pokemonName: getPokemonNameWithAffix(commandPhase.getPokemon()) }), 0);
|
||||
if (this.getCursor() === Command.POKEMON) {
|
||||
this.setCursor(Command.FIGHT);
|
||||
@ -108,6 +132,10 @@ export default class CommandUiHandler extends UiHandler {
|
||||
(globalScene.getCurrentPhase() as CommandPhase).handleCommand(Command.RUN, 0);
|
||||
success = true;
|
||||
break;
|
||||
case Command.TERA:
|
||||
ui.setMode(Mode.FIGHT, (globalScene.getCurrentPhase() as CommandPhase).getFieldIndex(), Command.TERA);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
(globalScene.getCurrentPhase() as CommandPhase).cancel();
|
||||
@ -115,23 +143,29 @@ export default class CommandUiHandler extends UiHandler {
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (cursor >= 2) {
|
||||
if (cursor === Command.POKEMON || cursor === Command.RUN) {
|
||||
success = this.setCursor(cursor - 2);
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (cursor < 2) {
|
||||
if (cursor === Command.FIGHT || cursor === Command.BALL) {
|
||||
success = this.setCursor(cursor + 2);
|
||||
}
|
||||
break;
|
||||
case Button.LEFT:
|
||||
if (cursor % 2 === 1) {
|
||||
if (cursor === Command.BALL || cursor === Command.RUN) {
|
||||
success = this.setCursor(cursor - 1);
|
||||
} else if ((cursor === Command.FIGHT || cursor === Command.POKEMON) && this.canTera()) {
|
||||
success = this.setCursor(Command.TERA);
|
||||
this.toggleTeraButton();
|
||||
}
|
||||
break;
|
||||
case Button.RIGHT:
|
||||
if (cursor % 2 === 0) {
|
||||
if (cursor === Command.FIGHT || cursor === Command.POKEMON) {
|
||||
success = this.setCursor(cursor + 1);
|
||||
} else if (cursor === Command.TERA) {
|
||||
success = this.setCursor(Command.FIGHT);
|
||||
this.toggleTeraButton();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -144,6 +178,17 @@ export default class CommandUiHandler extends UiHandler {
|
||||
return success;
|
||||
}
|
||||
|
||||
canTera(): boolean {
|
||||
const hasTeraMod = !!globalScene.getModifiers(TerastallizeAccessModifier).length;
|
||||
const currentTeras = globalScene.arena.playerTerasUsed;
|
||||
const plannedTera = globalScene.currentBattle.preTurnCommands[0]?.command === Command.TERA && this.fieldIndex > 0 ? 1 : 0;
|
||||
return hasTeraMod && (currentTeras + plannedTera) < 1;
|
||||
}
|
||||
|
||||
toggleTeraButton() {
|
||||
this.teraButton.setPipeline(globalScene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], ignoreTimeTint: true, teraColor: getTypeRgb(globalScene.getField()[this.fieldIndex].getTeraType()), isTerastallized: this.getCursor() === Command.TERA });
|
||||
}
|
||||
|
||||
getCursor(): number {
|
||||
return !this.fieldIndex ? this.cursor : this.cursor2;
|
||||
}
|
||||
@ -163,7 +208,12 @@ export default class CommandUiHandler extends UiHandler {
|
||||
this.commandsContainer.add(this.cursorObj);
|
||||
}
|
||||
|
||||
this.cursorObj.setPosition(-5 + (cursor % 2 === 1 ? 56 : 0), 8 + (cursor >= 2 ? 16 : 0));
|
||||
if (cursor === Command.TERA) {
|
||||
this.cursorObj.setVisible(false);
|
||||
} else {
|
||||
this.cursorObj.setPosition(-5 + (cursor % 2 === 1 ? 56 : 0), 8 + (cursor >= 2 ? 16 : 0));
|
||||
this.cursorObj.setVisible(true);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ export default class FightUiHandler extends UiHandler implements InfoToggle {
|
||||
private moveInfoOverlay : MoveInfoOverlay;
|
||||
|
||||
protected fieldIndex: number = 0;
|
||||
protected fromCommand: Command = Command.FIGHT;
|
||||
protected cursor2: number = 0;
|
||||
|
||||
constructor() {
|
||||
@ -114,6 +115,7 @@ export default class FightUiHandler extends UiHandler implements InfoToggle {
|
||||
super.show(args);
|
||||
|
||||
this.fieldIndex = args.length ? args[0] as number : 0;
|
||||
this.fromCommand = args.length > 1 ? args[1] as Command : Command.FIGHT;
|
||||
|
||||
const messageHandler = this.getUi().getMessageHandler();
|
||||
messageHandler.bg.setVisible(false);
|
||||
@ -140,7 +142,7 @@ export default class FightUiHandler extends UiHandler implements InfoToggle {
|
||||
|
||||
if (button === Button.CANCEL || button === Button.ACTION) {
|
||||
if (button === Button.ACTION) {
|
||||
if ((globalScene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, cursor, false)) {
|
||||
if ((globalScene.getCurrentPhase() as CommandPhase).handleCommand(this.fromCommand, cursor, false)) {
|
||||
success = true;
|
||||
} else {
|
||||
ui.playError();
|
||||
|
@ -133,7 +133,7 @@ export class FilterText extends Phaser.GameObjects.Container {
|
||||
const handler = ui.getHandler() as AwaitableUiHandler;
|
||||
handler.tutorialActive = true;
|
||||
// Switch to the dialog test window
|
||||
this.selections[index].setText(String(i18next.t(dialogueName)));
|
||||
this.selections[index].setText( dialogueName === "" ? this.defaultText : String(i18next.t(dialogueName)));
|
||||
ui.revertMode();
|
||||
this.onChange();
|
||||
},
|
||||
|
@ -14,7 +14,7 @@ import * as Utils from "./../utils";
|
||||
import Overrides from "#app/overrides";
|
||||
import i18next from "i18next";
|
||||
import { ShopCursorTarget } from "#app/enums/shop-cursor-target";
|
||||
import { IntegerHolder } from "./../utils";
|
||||
import { NumberHolder } from "./../utils";
|
||||
import Phaser from "phaser";
|
||||
import type { PokeballType } from "#enums/pokeball";
|
||||
|
||||
@ -191,7 +191,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||
|
||||
const typeOptions = args[1] as ModifierTypeOption[];
|
||||
const removeHealShop = globalScene.gameMode.hasNoShop;
|
||||
const baseShopCost = new IntegerHolder(globalScene.getWaveMoneyAmount(1));
|
||||
const baseShopCost = new NumberHolder(globalScene.getWaveMoneyAmount(1));
|
||||
globalScene.applyModifier(HealShopCostModifier, true, baseShopCost);
|
||||
const shopTypeOptions = !removeHealShop
|
||||
? getPlayerShopModifierTypeOptionsForWave(globalScene.currentBattle.waveIndex, baseShopCost.value)
|
||||
|
@ -16,7 +16,7 @@ import { pokemonFormChanges } from "#app/data/pokemon-forms";
|
||||
import type { LevelMoves } from "#app/data/balance/pokemon-level-moves";
|
||||
import { pokemonFormLevelMoves, pokemonSpeciesLevelMoves } from "#app/data/balance/pokemon-level-moves";
|
||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||
import { allSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
|
||||
import { allSpecies, getPokemonSpeciesForm, normalForm } from "#app/data/pokemon-species";
|
||||
import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters";
|
||||
import { starterPassiveAbilities } from "#app/data/balance/passives";
|
||||
import { Type } from "#enums/type";
|
||||
@ -383,7 +383,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
this.pokemonHatchedIcon.setScale(0.8);
|
||||
this.pokemonCaughtHatchedContainer.add(this.pokemonHatchedIcon);
|
||||
|
||||
this.pokemonShinyIcon = globalScene.add.sprite(14, 76, "shiny_icons");
|
||||
this.pokemonShinyIcon = globalScene.add.sprite(14, 117, "shiny_icons");
|
||||
this.pokemonShinyIcon.setOrigin(0.15, 0.2);
|
||||
this.pokemonShinyIcon.setScale(1);
|
||||
this.pokemonCaughtHatchedContainer.add(this.pokemonShinyIcon);
|
||||
@ -601,7 +601,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
const form = species.forms[formIndex];
|
||||
|
||||
// If this form has a specific set of moves, we get them.
|
||||
this.levelMoves = (formIndex > 0 && pokemonFormLevelMoves.hasOwnProperty(formIndex)) ? pokemonFormLevelMoves[species.speciesId][formIndex] : pokemonSpeciesLevelMoves[species.speciesId];
|
||||
this.levelMoves = (formIndex > 0 && pokemonFormLevelMoves.hasOwnProperty(species.speciesId) && pokemonFormLevelMoves[species.speciesId].hasOwnProperty(formIndex)) ? pokemonFormLevelMoves[species.speciesId][formIndex] : pokemonSpeciesLevelMoves[species.speciesId];
|
||||
this.ability1 = form.ability1;
|
||||
this.ability2 = (form.ability2 === form.ability1) ? undefined : form.ability2;
|
||||
this.abilityHidden = (form.abilityHidden === form.ability1) ? undefined : form.abilityHidden;
|
||||
@ -741,14 +741,16 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
return biomes;
|
||||
}
|
||||
|
||||
isCaught(otherSpeciesDexEntry?: DexEntry): bigint {
|
||||
isCaught(otherSpecies?: PokemonSpecies): bigint {
|
||||
if (globalScene.dexForDevs) {
|
||||
return 255n;
|
||||
}
|
||||
|
||||
const dexEntry = otherSpeciesDexEntry ? otherSpeciesDexEntry : this.speciesStarterDexEntry;
|
||||
const species = otherSpecies ? otherSpecies : this.species;
|
||||
const dexEntry = globalScene.gameData.dexData[species.speciesId];
|
||||
const starterDexEntry = globalScene.gameData.dexData[this.getStarterSpeciesId(species.speciesId)];
|
||||
|
||||
return dexEntry?.caughtAttr ?? 0n;
|
||||
return (dexEntry?.caughtAttr ?? 0n) & (starterDexEntry?.caughtAttr ?? 0n) & species.getFullUnlocksData();
|
||||
}
|
||||
/**
|
||||
* Check whether a given form is caught for a given species.
|
||||
@ -765,11 +767,9 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
}
|
||||
const species = otherSpecies ? otherSpecies : this.species;
|
||||
const formIndex = otherFormIndex !== undefined ? otherFormIndex : this.formIndex;
|
||||
const dexEntry = globalScene.gameData.dexData[species.speciesId];
|
||||
const caughtAttr = this.isCaught(species);
|
||||
|
||||
const isFormCaught = dexEntry ?
|
||||
(dexEntry.caughtAttr & globalScene.gameData.getFormAttr(formIndex ?? 0)) > 0n
|
||||
: false;
|
||||
const isFormCaught = (caughtAttr & globalScene.gameData.getFormAttr(formIndex ?? 0)) > 0n;
|
||||
return isFormCaught;
|
||||
}
|
||||
|
||||
@ -783,8 +783,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
*/
|
||||
initStarterPrefs(): StarterAttributes {
|
||||
const starterAttributes : StarterAttributes | null = this.species ? { ...this.savedStarterAttributes } : null;
|
||||
const dexEntry = globalScene.gameData.dexData[this.species.speciesId];
|
||||
const caughtAttr = this.isCaught(dexEntry);
|
||||
const caughtAttr = this.isCaught();
|
||||
|
||||
// no preferences or Pokemon wasn't caught, return empty attribute
|
||||
if (!starterAttributes || !caughtAttr) {
|
||||
@ -1235,7 +1234,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
|
||||
case MenuOptions.BIOMES:
|
||||
|
||||
if (!(this.isCaught() || this.speciesStarterDexEntry?.seenAttr)) {
|
||||
if (!(isCaught || this.speciesStarterDexEntry?.seenAttr)) {
|
||||
error = true;
|
||||
} else {
|
||||
this.blockInput = true;
|
||||
@ -1372,8 +1371,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
});
|
||||
this.evolutions.map(evo => {
|
||||
const evoSpecies = allSpecies.find(species => species.speciesId === evo.speciesId);
|
||||
const evoSpeciesStarterDexEntry = evoSpecies ? globalScene.gameData.dexData[evoSpecies.speciesId] : undefined;
|
||||
const isCaughtEvo = this.isCaught(evoSpeciesStarterDexEntry) ? true : false;
|
||||
const isCaughtEvo = this.isCaught(evoSpecies) ? true : false;
|
||||
// Attempts to find the formIndex of the evolved species
|
||||
const newFormKey = evo.evoFormKey ? evo.evoFormKey : (this.species.forms.length > 0 ? this.species.forms[this.formIndex].formKey : "");
|
||||
const matchingForm = evoSpecies?.forms.find(form => form.formKey === newFormKey);
|
||||
@ -1535,6 +1533,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
this.pokemonShinyIcon.setVisible(true);
|
||||
|
||||
starterAttributes.shiny = true;
|
||||
this.savedStarterAttributes.shiny = starterAttributes.shiny;
|
||||
} else {
|
||||
let newVariant = props.variant;
|
||||
do {
|
||||
@ -1583,7 +1582,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
if (this.species.forms[newFormIndex].isStarterSelectable || globalScene.dexForDevs) { // TODO: are those bangs correct?
|
||||
break;
|
||||
}
|
||||
} while (newFormIndex !== props.formIndex);
|
||||
} while (newFormIndex !== props.formIndex || this.species.forms[newFormIndex].isUnobtainable);
|
||||
starterAttributes.form = newFormIndex; // store the selected form
|
||||
this.savedStarterAttributes.form = starterAttributes.form;
|
||||
this.formIndex = newFormIndex;
|
||||
@ -1688,7 +1687,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
}
|
||||
this.pokemonCandyCountText.setText(`x${starterData.candyCount}`);
|
||||
|
||||
const egg = new Egg({ scene: globalScene, species: this.species.speciesId, sourceType: EggSourceType.SAME_SPECIES_EGG });
|
||||
const egg = new Egg({ scene: globalScene, species: this.starterId, sourceType: EggSourceType.SAME_SPECIES_EGG });
|
||||
egg.addEggToGameData();
|
||||
|
||||
globalScene.gameData.saveSystem().then(success => {
|
||||
@ -1856,6 +1855,9 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
if (this.canCycleGender) {
|
||||
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Gender, gamepadType, this.genderIconElement, this.genderLabel);
|
||||
}
|
||||
} else {
|
||||
// Making space for "Uncaught" text
|
||||
this.instructionRowY += 8;
|
||||
}
|
||||
if (this.canCycleForm) {
|
||||
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Form, gamepadType, this.formIconElement, this.formLabel);
|
||||
@ -2093,7 +2095,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
if (species) {
|
||||
const dexEntry = globalScene.gameData.dexData[species.speciesId];
|
||||
|
||||
const caughtAttr = this.isCaught(dexEntry);
|
||||
const caughtAttr = this.isCaught(species);
|
||||
|
||||
if (!caughtAttr) {
|
||||
const props = this.starterAttributes;
|
||||
@ -2240,13 +2242,11 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
this.pokemonCandyContainer.setVisible(true);
|
||||
|
||||
if (pokemonPrevolutions.hasOwnProperty(species.speciesId)) {
|
||||
this.pokemonShinyIcon.setY(135);
|
||||
this.pokemonShinyIcon.setFrame(getVariantIcon(variant));
|
||||
this.pokemonHatchedIcon.setVisible(false);
|
||||
this.pokemonHatchedCountText.setVisible(false);
|
||||
this.pokemonFormText.setY(36);
|
||||
} else {
|
||||
this.pokemonShinyIcon.setY(117);
|
||||
this.pokemonHatchedIcon.setVisible(true);
|
||||
this.pokemonHatchedCountText.setVisible(true);
|
||||
this.pokemonFormText.setY(42);
|
||||
@ -2276,7 +2276,12 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
if (isFormCaught || isFormSeen) {
|
||||
const speciesForm = getPokemonSpeciesForm(species.speciesId, formIndex!); // TODO: is the bang correct?
|
||||
this.setTypeIcons(speciesForm.type1, speciesForm.type2);
|
||||
this.pokemonFormText.setText(species.getFormNameToDisplay(formIndex));
|
||||
// TODO: change this once forms are refactored
|
||||
if (normalForm.includes(species.speciesId) && !formIndex) {
|
||||
this.pokemonFormText.setText("");
|
||||
} else {
|
||||
this.pokemonFormText.setText(species.getFormNameToDisplay(formIndex));
|
||||
}
|
||||
this.pokemonFormText.setVisible(true);
|
||||
if (!isFormCaught) {
|
||||
this.pokemonFormText.setY(18);
|
||||
@ -2321,7 +2326,8 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
|
||||
*/
|
||||
getCurrentDexProps(speciesId: number): bigint {
|
||||
let props = 0n;
|
||||
const caughtAttr = globalScene.gameData.dexData[speciesId].caughtAttr;
|
||||
const species = allSpecies.find(sp => sp.speciesId === speciesId);
|
||||
const caughtAttr = globalScene.gameData.dexData[speciesId].caughtAttr & globalScene.gameData.dexData[this.getStarterSpeciesId(speciesId)].caughtAttr & (species?.getFullUnlocksData() ?? 0n);
|
||||
|
||||
/* this checks the gender of the pokemon; this works by checking a) that the starter preferences for the species exist, and if so, is it female. If so, it'll add DexAttr.FEMALE to our temp props
|
||||
* It then checks b) if the caughtAttr for the pokemon is female and NOT male - this means that the ONLY gender we've gotten is female, and we need to add DexAttr.FEMALE to our temp props
|
||||
|
@ -115,6 +115,10 @@ export default class PokedexScanUiHandler extends FormModalUiHandler {
|
||||
|
||||
this.reduceKeys();
|
||||
|
||||
setTimeout(() => {
|
||||
input.setFocus(); // Focus after a short delay to avoid unwanted input
|
||||
}, 50);
|
||||
|
||||
input.on("keydown", (inputObject, evt: KeyboardEvent) => {
|
||||
if ([ "escape", "space" ].some((v) => v === evt.key.toLowerCase() || v === evt.code.toLowerCase()) && ui.getMode() === Mode.AUTO_COMPLETE) {
|
||||
// Delete autocomplete list and recovery focus.
|
||||
@ -169,7 +173,8 @@ export default class PokedexScanUiHandler extends FormModalUiHandler {
|
||||
this.submitAction = (_) => {
|
||||
if (ui.getMode() === Mode.POKEDEX_SCAN) {
|
||||
this.sanitizeInputs();
|
||||
const sanitizedName = btoa(unescape(encodeURIComponent(this.inputs[0].text)));
|
||||
const outputName = this.reducedKeys.includes(this.inputs[0].text) ? this.inputs[0].text : "";
|
||||
const sanitizedName = btoa(unescape(encodeURIComponent(outputName)));
|
||||
config.buttonActions[0](sanitizedName);
|
||||
return true;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import { speciesEggMoves } from "#app/data/balance/egg-moves";
|
||||
import { pokemonFormLevelMoves, pokemonSpeciesLevelMoves } from "#app/data/balance/pokemon-level-moves";
|
||||
import type { PokemonForm } from "#app/data/pokemon-species";
|
||||
import type PokemonSpecies from "#app/data/pokemon-species";
|
||||
import { allSpecies, getPokemonSpeciesForm, getPokerusStarters } from "#app/data/pokemon-species";
|
||||
import { allSpecies, getPokemonSpeciesForm, getPokerusStarters, normalForm } from "#app/data/pokemon-species";
|
||||
import { getStarterValueFriendshipCap, speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters";
|
||||
import { catchableSpecies } from "#app/data/balance/biomes";
|
||||
import { Type } from "#enums/type";
|
||||
@ -336,6 +336,8 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
const costReductionLabels = [
|
||||
new DropDownLabel(i18next.t("filterBar:costReduction"), undefined, DropDownState.OFF),
|
||||
new DropDownLabel(i18next.t("filterBar:costReductionUnlocked"), undefined, DropDownState.ON),
|
||||
new DropDownLabel(i18next.t("filterBar:costReductionUnlockedOne"), undefined, DropDownState.ONE),
|
||||
new DropDownLabel(i18next.t("filterBar:costReductionUnlockedTwo"), undefined, DropDownState.TWO),
|
||||
new DropDownLabel(i18next.t("filterBar:costReductionUnlockable"), undefined, DropDownState.UNLOCKABLE),
|
||||
new DropDownLabel(i18next.t("filterBar:costReductionLocked"), undefined, DropDownState.EXCLUDE),
|
||||
];
|
||||
@ -411,15 +413,15 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
this.iconAnimHandler = new PokemonIconAnimHandler();
|
||||
this.iconAnimHandler.setup();
|
||||
|
||||
this.pokemonNumberText = addTextObject(6, 140, "", TextStyle.SUMMARY);
|
||||
this.pokemonNumberText = addTextObject(6, 141, "", TextStyle.SUMMARY);
|
||||
this.pokemonNumberText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonNumberText);
|
||||
|
||||
this.pokemonNameText = addTextObject(6, 127, "", TextStyle.SUMMARY);
|
||||
this.pokemonNameText = addTextObject(6, 128, "", TextStyle.SUMMARY);
|
||||
this.pokemonNameText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonNameText);
|
||||
|
||||
this.pokemonFormText = addTextObject(6, 122, "", TextStyle.PARTY, { fontSize: textSettings.instructionTextSize });
|
||||
this.pokemonFormText = addTextObject(6, 121, "", TextStyle.PARTY, { fontSize: textSettings.instructionTextSize });
|
||||
this.pokemonFormText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonFormText);
|
||||
|
||||
@ -537,6 +539,8 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
this.starterSelectContainer.bringToTop(this.filterBarContainer);
|
||||
this.initTutorialOverlay(this.starterSelectContainer);
|
||||
this.starterSelectContainer.bringToTop(this.starterSelectMessageBoxContainer);
|
||||
this.starterSelectContainer.bringToTop(this.pokemonNameText);
|
||||
this.starterSelectContainer.bringToTop(this.pokemonFormText);
|
||||
}
|
||||
|
||||
show(args: any[]): boolean {
|
||||
@ -565,7 +569,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
|
||||
this.starterPreferences[species.speciesId] = this.initStarterPrefs(species);
|
||||
|
||||
if (dexEntry.caughtAttr || globalScene.dexForDevs) {
|
||||
if ((dexEntry.caughtAttr & species.getFullUnlocksData()) || globalScene.dexForDevs) {
|
||||
icon.clearTint();
|
||||
} else if (dexEntry.seenAttr) {
|
||||
icon.setTint(0x808080);
|
||||
@ -606,7 +610,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
return {};
|
||||
}
|
||||
|
||||
const caughtAttr = dexEntry.caughtAttr;
|
||||
const caughtAttr = dexEntry.caughtAttr & species.getFullUnlocksData();
|
||||
|
||||
const hasShiny = caughtAttr & DexAttr.SHINY;
|
||||
const hasNonShiny = caughtAttr & DexAttr.NON_SHINY;
|
||||
@ -1255,7 +1259,9 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
|
||||
// First, ensure you have the caught attributes for the species else default to bigint 0
|
||||
// TODO: This might be removed depending on how accessible we want the pokedex function to be
|
||||
const caughtAttr = globalScene.gameData.dexData[container.species.speciesId]?.caughtAttr || BigInt(0);
|
||||
const caughtAttr = (globalScene.gameData.dexData[container.species.speciesId]?.caughtAttr || BigInt(0)) &
|
||||
(globalScene.gameData.dexData[this.getStarterSpeciesId(container.species.speciesId)]?.caughtAttr || BigInt(0)) &
|
||||
container.species.getFullUnlocksData();
|
||||
const starterData = globalScene.gameData.starterData[starterId];
|
||||
const isStarterProgressable = speciesEggMoves.hasOwnProperty(starterId);
|
||||
|
||||
@ -1292,7 +1298,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
if (fitsEggMove1 && !fitsLevelMove1) {
|
||||
container.eggMove1Icon.setVisible(true);
|
||||
const em1 = eggMoves.findIndex(name => name === selectedMove1);
|
||||
if ((starterData[starterId].eggMoves & (1 << em1)) === 0) {
|
||||
if ((starterData.eggMoves & (1 << em1)) === 0) {
|
||||
container.eggMove1Icon.setTint(0x808080);
|
||||
} else {
|
||||
container.eggMove1Icon.clearTint();
|
||||
@ -1303,7 +1309,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
if (fitsEggMove2 && !fitsLevelMove2) {
|
||||
container.eggMove2Icon.setVisible(true);
|
||||
const em2 = eggMoves.findIndex(name => name === selectedMove2);
|
||||
if ((starterData[starterId].eggMoves & (1 << em2)) === 0) {
|
||||
if ((starterData.eggMoves & (1 << em2)) === 0) {
|
||||
container.eggMove2Icon.setTint(0x808080);
|
||||
} else {
|
||||
container.eggMove2Icon.clearTint();
|
||||
@ -1580,11 +1586,12 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
}
|
||||
|
||||
const speciesId = container.species.speciesId;
|
||||
const caughtAttr = globalScene.gameData.dexData[speciesId].caughtAttr & globalScene.gameData.dexData[this.getStarterSpeciesId(speciesId)].caughtAttr & container.species.getFullUnlocksData();
|
||||
this.updateStarterValueLabel(container);
|
||||
|
||||
container.label.setVisible(true);
|
||||
const speciesVariants = speciesId && globalScene.gameData.dexData[speciesId].caughtAttr & DexAttr.SHINY
|
||||
? [ DexAttr.DEFAULT_VARIANT, DexAttr.VARIANT_2, DexAttr.VARIANT_3 ].filter(v => !!(globalScene.gameData.dexData[speciesId].caughtAttr & v))
|
||||
const speciesVariants = speciesId && caughtAttr & DexAttr.SHINY
|
||||
? [ DexAttr.DEFAULT_VARIANT, DexAttr.VARIANT_2, DexAttr.VARIANT_3 ].filter(v => !!(caughtAttr & v))
|
||||
: [];
|
||||
for (let v = 0; v < 3; v++) {
|
||||
const hasVariant = speciesVariants.length > v;
|
||||
@ -1595,7 +1602,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
}
|
||||
|
||||
container.starterPassiveBgs.setVisible(!!globalScene.gameData.starterData[this.getStarterSpeciesId(speciesId)].passiveAttr);
|
||||
container.hiddenAbilityIcon.setVisible(!!globalScene.gameData.dexData[speciesId].caughtAttr && !!(globalScene.gameData.starterData[this.getStarterSpeciesId(speciesId)].abilityAttr & 4));
|
||||
container.hiddenAbilityIcon.setVisible(!!caughtAttr && !!(globalScene.gameData.starterData[this.getStarterSpeciesId(speciesId)].abilityAttr & 4));
|
||||
container.classicWinIcon.setVisible(globalScene.gameData.starterData[this.getStarterSpeciesId(speciesId)].classicWinCount > 0);
|
||||
container.favoriteIcon.setVisible(this.starterPreferences[speciesId]?.favorite ?? false);
|
||||
|
||||
@ -1698,7 +1705,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
|
||||
openFormTray(species: PokemonSpecies): boolean {
|
||||
|
||||
this.trayForms = species.forms;
|
||||
this.trayForms = species.forms.filter(f => !f.isUnobtainable);
|
||||
|
||||
this.trayNumIcons = this.trayForms.length;
|
||||
this.trayRows = Math.floor(this.trayNumIcons / 9) + (this.trayNumIcons % 9 === 0 ? 0 : 1);
|
||||
@ -1729,7 +1736,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
|
||||
this.trayContainers = [];
|
||||
this.trayForms.map((f, index) => {
|
||||
const isFormCaught = dexEntry ? (dexEntry.caughtAttr & globalScene.gameData.getFormAttr(f.formIndex ?? 0)) > 0n : false;
|
||||
const isFormCaught = dexEntry ? (dexEntry.caughtAttr & species.getFullUnlocksData() & globalScene.gameData.getFormAttr(f.formIndex ?? 0)) > 0n : false;
|
||||
const isFormSeen = dexEntry ? (dexEntry.seenAttr & globalScene.gameData.getFormAttr(f.formIndex ?? 0)) > 0n : false;
|
||||
const formContainer = new PokedexMonContainer(species, { formIndex: f.formIndex, female: props.female, shiny: props.shiny, variant: props.variant });
|
||||
this.iconAnimHandler.addOrUpdate(formContainer.icon, PokemonIconAnimMode.NONE);
|
||||
@ -1866,6 +1873,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
} else {
|
||||
this.pokemonNumberText.setText(species ? i18next.t("pokedexUiHandler:pokemonNumber") + padInt(species.speciesId, 4) : "");
|
||||
this.pokemonNameText.setText(species ? "???" : "");
|
||||
this.pokemonFormText.setText("");
|
||||
this.type1Icon.setVisible(false);
|
||||
this.type2Icon.setVisible(false);
|
||||
if (species) {
|
||||
@ -1899,8 +1907,9 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
|
||||
if (species) {
|
||||
const dexEntry = globalScene.gameData.dexData[species.speciesId];
|
||||
const caughtAttr = dexEntry.caughtAttr & globalScene.gameData.dexData[this.getStarterSpeciesId(species.speciesId)].caughtAttr & species.getFullUnlocksData();
|
||||
|
||||
if (!dexEntry.caughtAttr) {
|
||||
if (!caughtAttr) {
|
||||
const props = this.getSanitizedProps(globalScene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)));
|
||||
|
||||
if (shiny === undefined) {
|
||||
@ -1917,7 +1926,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
const isFormCaught = dexEntry ? (dexEntry.caughtAttr & globalScene.gameData.getFormAttr(formIndex ?? 0)) > 0n : false;
|
||||
const isFormCaught = dexEntry ? (caughtAttr & globalScene.gameData.getFormAttr(formIndex ?? 0)) > 0n : false;
|
||||
const isFormSeen = dexEntry ? (dexEntry.seenAttr & globalScene.gameData.getFormAttr(formIndex ?? 0)) > 0n : false;
|
||||
|
||||
const assetLoadCancelled = new BooleanHolder(false);
|
||||
@ -1949,19 +1958,24 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
}
|
||||
|
||||
if (isFormCaught || isFormSeen || globalScene.dexForDevs) {
|
||||
this.pokemonFormText.setText("Form Text");
|
||||
// TODO: change this once forms are refactored
|
||||
if (normalForm.includes(species.speciesId) && !formIndex) {
|
||||
this.pokemonFormText.setText("");
|
||||
} else {
|
||||
this.pokemonFormText.setText(species.getFormNameToDisplay(formIndex, false));
|
||||
}
|
||||
} else {
|
||||
this.pokemonFormText.setText("");
|
||||
}
|
||||
|
||||
if (isFormCaught || isFormSeen || globalScene.dexForDevs) {
|
||||
const speciesForm = getPokemonSpeciesForm(species.speciesId, 0); // TODO: always selecting the first form
|
||||
const speciesForm = getPokemonSpeciesForm(species.speciesId, formIndex ?? 0); // TODO: always selecting the first form
|
||||
this.setTypeIcons(speciesForm.type1, speciesForm.type2);
|
||||
} else {
|
||||
this.setTypeIcons(null, null);
|
||||
}
|
||||
|
||||
if (species?.forms?.length > 1) {
|
||||
if (species?.forms?.filter(f => !f.isUnobtainable).length > 1) {
|
||||
if (!this.showingTray) {
|
||||
this.showFormTrayIconElement.setVisible(true);
|
||||
this.showFormTrayLabel.setVisible(true);
|
||||
@ -2054,7 +2068,8 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
||||
*/
|
||||
getCurrentDexProps(speciesId: number): bigint {
|
||||
let props = 0n;
|
||||
const caughtAttr = globalScene.gameData.dexData[speciesId].caughtAttr;
|
||||
const species = allSpecies.find(sp => sp.speciesId === speciesId);
|
||||
const caughtAttr = globalScene.gameData.dexData[speciesId].caughtAttr & globalScene.gameData.dexData[this.getStarterSpeciesId(speciesId)].caughtAttr & (species?.getFullUnlocksData() ?? 0n);
|
||||
|
||||
/* this checks the gender of the pokemon; this works by checking a) that the starter preferences for the species exist, and if so, is it female. If so, it'll add DexAttr.FEMALE to our temp props
|
||||
* It then checks b) if the caughtAttr for the pokemon is female and NOT male - this means that the ONLY gender we've gotten is female, and we need to add DexAttr.FEMALE to our temp props
|
||||
|
@ -420,17 +420,6 @@ export default class RunInfoUiHandler extends UiHandler {
|
||||
private parseTrainerDefeat(enemyContainer: Phaser.GameObjects.Container) {
|
||||
// Loads and adds trainer sprites to the UI
|
||||
this.showTrainerSprites(enemyContainer);
|
||||
// Determining which Terastallize Modifier belongs to which Pokemon
|
||||
// Creates a dictionary {PokemonId: TeraShardType}
|
||||
const teraPokemon = {};
|
||||
this.runInfo.enemyModifiers.forEach((m) => {
|
||||
const modifier = m.toModifier(this.modifiersModule[m.className]);
|
||||
if (modifier instanceof Modifier.TerastallizeModifier) {
|
||||
const teraDetails = modifier?.getArgs();
|
||||
const pkmnId = teraDetails[0];
|
||||
teraPokemon[pkmnId] = teraDetails[1];
|
||||
}
|
||||
});
|
||||
|
||||
// Creates the Pokemon icons + level information and adds it to enemyContainer
|
||||
// 2 Rows x 3 Columns
|
||||
@ -444,18 +433,6 @@ export default class RunInfoUiHandler extends UiHandler {
|
||||
enemyData["player"] = true;
|
||||
const enemy = enemyData.toPokemon();
|
||||
const enemyIcon = globalScene.addPokemonIcon(enemy, 0, 0, 0, 0);
|
||||
// Applying Terastallizing Type tint to Pokemon icon
|
||||
// If the Pokemon is a fusion, it has two sprites and so, the tint has to be applied to each icon separately
|
||||
const enemySprite1 = enemyIcon.list[0] as Phaser.GameObjects.Sprite;
|
||||
const enemySprite2 = (enemyIcon.list.length > 1) ? enemyIcon.list[1] as Phaser.GameObjects.Sprite : undefined;
|
||||
if (teraPokemon[enemyData.id]) {
|
||||
const teraTint = getTypeRgb(teraPokemon[enemyData.id]);
|
||||
const teraColor = new Phaser.Display.Color(teraTint[0], teraTint[1], teraTint[2]);
|
||||
enemySprite1.setTint(teraColor.color);
|
||||
if (enemySprite2) {
|
||||
enemySprite2.setTint(teraColor.color);
|
||||
}
|
||||
}
|
||||
enemyIcon.setPosition(39 * (e % 3) + 5, (35 * pokemonRowHeight));
|
||||
const enemyLevel = addTextObject(43 * (e % 3), (27 * (pokemonRowHeight + 1)), `${i18next.t("saveSlotSelectUiHandler:lv")}${Utils.formatLargeNumber(enemy.level, 1000)}`, isBoss ? TextStyle.PARTY_RED : TextStyle.PARTY, { fontSize: "54px" });
|
||||
enemyLevel.setShadow(0, 0, undefined);
|
||||
|
@ -88,7 +88,7 @@ const languageSettings: { [key: string]: LanguageSetting } = {
|
||||
starterInfoXPos: 33,
|
||||
},
|
||||
"es-ES":{
|
||||
starterInfoTextSize: "56px",
|
||||
starterInfoTextSize: "52px",
|
||||
instructionTextSize: "35px",
|
||||
},
|
||||
"fr":{
|
||||
|
@ -334,6 +334,7 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||
}
|
||||
this.pokemonSprite.setPipelineData("teraColor", getTypeRgb(this.pokemon.getTeraType()));
|
||||
this.pokemonSprite.setPipelineData("isTerastallized", this.pokemon.isTerastallized);
|
||||
this.pokemonSprite.setPipelineData("ignoreTimeTint", true);
|
||||
this.pokemonSprite.setPipelineData("spriteKey", this.pokemon.getSpriteKey());
|
||||
this.pokemonSprite.setPipelineData("shiny", this.pokemon.shiny);
|
||||
@ -782,7 +783,7 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
if (types.length > 1) {
|
||||
profileContainer.add(getTypeIcon(1, types[1]));
|
||||
}
|
||||
if (this.pokemon?.isTerastallized()) {
|
||||
if (this.pokemon?.isTerastallized) {
|
||||
profileContainer.add(getTypeIcon(types.length, this.pokemon.getTeraType(), true));
|
||||
}
|
||||
|
||||
|
@ -342,13 +342,6 @@ export class NumberHolder {
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated Use {@linkcode NumberHolder} */
|
||||
export class IntegerHolder extends NumberHolder {
|
||||
constructor(value: number) {
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
|
||||
export class FixedInt {
|
||||
public readonly value: number;
|
||||
|
||||
|