I don't mind at all! Glad you liked it :)
(It's not actually a NES homebrew though, I just tried to stick close to resolution / sound standards for verisimilitude but it's a Game Maker EXE and can't actually be run as a ROM)
Currently, this code block in battlecontrol's step event is what actually plays the animation (using the animation object of the move). a_user is the monster object who is doing the action, and a_targ is an array of one or more monster objects that are being targeted. (And the target can contain the user, e.g. if the move is a buff or recovery action). So, this is the "entry point" where you'd want to put any new behavior.

Your question is a bit vague but I think this is what you're asking for:
You don't even need to initialize the struct to all NONE's since variable_struct_exists exists - if e.g. variable_struct_exists("physical") is false when checking the monster species' animations, you can conclude it has no special animation for physical attacks and just skip overriding its sprite.
(I'm assuming you mean "sprite animations" here but if you want attack control objects you could pretty much set up the data the same way)
I think the easiest way to add this would be having a new global array of "mega evolutions data" which has three items per row: base monster, mega monster, and held item needed for the transformation.
Ah... yeah, the code assumes the origin for cylinders is in the center, so having it be in the top left corner will offset everything by the radius amount on both axes. Glad that got sorted out in the end at least.
The player movement (the vast majority of movement is done in psbp_inertia_horizontal / psbp_inertia_vertical) mainly uses two functions, terrain_hit_pilloid_cheap and slope_hit_optimized, the latter of which in turn uses terrain_buffer_lookup_verticalslice. Both of these intentionally just check 3 points (XY center @ Z bottom, Z top, and Z centerpoint) since collision checking turned out to be the most expensive operation in the game. But there's a dummied-out alternate version of terrain_hit_pilloid_cheap that does check the full 12 points (taking the radius into account). Replacing the 3-point version with this, and then using slope_hit_pilloid_cheap in the player inertia functions instead of slope_hit_optimized, should restore the old collision checking as it was. (Note that slope_hit_optimized uses a z height argument that slope_hit_pilloid_cheap doesn't use so you might need to remove that to avoid GM complaining about passing too many arguments)
Currently evolutions already are an array, with zero or more tuples [type, parameter, evoSpecies]. For item split evolutions you could just add them there, but be triggered by different items.
For levels I'm thinking the easiest would be adding new evolution types, e.g. evotype_LEVEL_SPLIT_PHYS_ATK and evotype_LEVEL_SPLIT_DAYNIGHT_PHYS_DEF for a monster that becomes one species when its ATK is higher and another if its DEF is higher. These come in pairs (or triplets, etc), one type for each "branch" of evolution and then you'd give the monster one evolution tuple for each branch. (So e.g. [[evotype_LEVEL_SPLIT_PHYS_ATK, 10, mon_SWORDY], [evotype_LEVEL_SPLIT_DAYNIGHT_PHYS_DEF, 10, mon_SHIELDY]] as the evolutionlist)
The script amp_earn_exp is also responsible for keeping track of pending evolutions, and currently it only checks for evotype_LEVEL here. You would add the new types here as well, but have them only enqueue the new evolution if the condition for that "branch" is met (and then make sure to write conditions so that only one can be met at a time)
The game already keeps track of which monsters you've owned, the global.monsters_caught array (indexed by monster species ID). So for instance you could have enemy side's obj_battlemonsterhud check if global.monsters_caught[global.active_monster_party[monster.amp_id,amp_MONID]] is true (and if so, draw the "owned" icon)
You can check how many enemies are alive by running
var num_alive = 0;
for(var mon = AMP_FIRST_ENEMY; mon < AMP_FIRST_ENEMY + PARTYSIZE_MAX_ENEMY; mon++){
if(global.active_monster_party[mon,amp_HP] > 0){
num_alive++;
}
}You'd probably want to count once at the start of the battle (within bcontrolstate_ANNOUNCE_TRAINER) to get the TOTAL amount of monsters, and then count the number of currently available ones in the Draw event (so you can cross out KO'd monsters when drawing)
Hmmm... my gut instinct is that it might be placed on a boundary for the collision checking grid, and is erroneously only added to ONE of the cells (objects that overlap a boundary are supposed to be added to all cells they touch).
I would check this by copypasting the weird cylinder and placing it in a bunch of different positions (altering both X and Y) and seeing if they are also glitchy or will work as intended. In particular if you move it sideways along the axis it's "cut off" at, EVERY cylinder at those coordinates would have half of its collision data missing, and if you move it "into the level"-wards, only the overlapping section would be missing collision data.
(And if this is actually the case, the next step would be adding some debug messages in terrain_buffer_add to investigate further, to e.g. print the "key" and ensure it gets added to every cell you expect)
Relatedly, is this line where the collision is broken the zero of any coordinate? I just realized terrain_buffer_get_key is using the "div" operator (integer division) and if GM interprets "round down" as "round towards zero" (instead of "round towards negative infinity" which is the correct definition) both the collision grid cells directly adjacent to the zero of any axis will map to the same key.
The idea was to use the map sprite as a special icon when looking at the status screen (e.g. on the map) but I ended up never using it (I did a code search and there's no hits for it) so you can go ahead and use it for whatever you want! :)
Internally it's global.monster_data[monsterID,mond_SPRITE_SMALL] ("SPRITE_SMALL" rather than "SPRITE_MAP")
I'm thinking something like this:

Overworld sprites should "just work", draw_sprite_gridbased uses a percentage of the sprite asset's size so the only thing that matters is that it's a 4x4 grid.
For the tiles, change the TILESIZE macro-constant to 32 (it's set in init_constants) and then also update the settings of tileset_indoors and tileset_outdoors to be 32 (the underlying sprites also need to be resized to 640x512 for the information about how many columns of tiles are in the sets to be accurate.
Changing the sizes should be safe (I use the TILESIZE constant everywhere) except I don't know what Game Maker will do with pre-existing tile layers when you change the tilesize. It's probably best to make a backup of your project (File --> Export Project --> YYZ) before you do this.
Ah... that code only adjusts the object's regular coordinates and not the individual points of the footpath, so they're desynchronized. I wonder if it messes with how the new points are calculated when the rotations are applied? editor_unarrayify_patternobject doesn't actually use the object coordinates at all (only the individual points, which are absolute values relative to the editormarker and thus ALSO not affected by the footpath object's coordinates) so I don't see how this would affect it, but I also haven't touched this stuff since march 2023 so my memory is quite fuzzy.
Either way, I think the better way to fix it would be to, after updating the coordinates, check if oldcoords[3] is obj_footpath, and if so oldcoords[14] is the number of points; 15,16,17 is the first point's x,y,z coordinates and so on - you'd go through each such trio of points in ret_pattern[c] (which is the updated version of oldcoords) and subtracting xmin, ymin and zmin.
Yeah, and the prefab system uses the copy/paste system internally so they should behave the same...
The only thing I can think of that could differ is how editor_arrayify_patternobject subtracts the editormarker's position from each point in the path when copying (to get relative distances that can be rotated), does that somehow act differently when loading a prefab because the marker could be anywhere perhaps? (instead of a place that includes the path's origin, which is guaranteed when copypasting)
I did some test with both prefabs and copypastes, and it works for me (including rotations, and copying a footpath + moving along an axis causing the copy to be parallel to the original), but I did notice a bug - if you don't press "enter" to finalize the path data before saving a prefab file it gets saved in an incomplete state. This might be what's happening here?
The only other things I can think of is if the origin coordinate calculation gets messed up when you load the prefab with the marker size larger than 1x1x1 or if there was some funky interaction with you having something in the copypaste buffer already when loading a prefab - does it behave as expected if you press "alt" to quick-reset the cursor before loading the prefab?
Thank you so much! ^__^
My original plan was to make it commercial, but then all my first drafts ended up being exact copies of Deltarune UI (without me even trying to rip it off) and I felt I shouldn't push my luck. Plus, a large part of the people interested in making UT/DR fangames are too young to be able to buy stuff online and it would be counterproductive to exclude them.
A lot of the stuff in the engine is actually things I've been doing for years - having global arrays with all the data set up in script asset scope + a general "everything is data" approach, cutscenes being queues of command-argument pairs, having generic objects you customize with GUI variables... the two main new things are named position markers and having a shared pathfinding system that both NPCs and players can use in cutscenes; both of those experiments turned out great so it'll be fun experimenting with them more in the future.
So did I, which was what gave me the idea to make this one :)
My original plan was to charge for it, but all my first drafts kept accidentally being way too close to what's actually in Deltarune and I felt like it was too much of a legal risk (I don't want to get run over by a dog in a toy car in a dark alley...). Also a pretty sizeable part of the fanbase is too young to be able to buy stuff online, and that would exclude them from the engine, which felt counterproductive.
I had a look in the codebase and yeah, the code has been completely removed so they're completely gone, they're not just disabled.
The reasoning for removing stuff I remember at least, I never was happy with how the code basically needed a completely separate copy of the behavior for each axis (applying to both rendering and collision). Rotating cylinder objects in a prefab/copypaste didn't work as expected either (since they would have a rotated size but still be cylindric along the original axis) and starting to need special behavior for rotating certain objects felt like such a kludge I just couldn't keep going anymore. And the collision code for tunnels especially always was a nightmare, they are paper-thin so for smaller tunnels it was easy to get stuck, and there was no good way to connect tunnels to a start point or a corner that LOOKED right (for making sewers etc) so I always felt like they were a total failure. For making tunnel areas I'd recommend using separate prisms for the floor and ceiling instead, they even can be cobbled together into smooth rounded corners.
There's no way to rotate things around other axes. A lot of stuff treats the vertical axis in a special way (since Game Maker doesn't have a Z axis natively) so a lot of code (especially the collision code) wouldn't know what to do with e.g. a prism protruding along the X axis instead of at the top.
The World Map Chunk Map is the data that keeps track of the coordinates where level files should be loaded (or in other words, it places the handmade map chunks on the world map), the geometry is stored in a different folder called the world cache. It's found in AppData --> Local --> (name of the project) --> cache_world. Delete every file inside this folder and it should be regenerated next time you run the game.
Oops, I must've forgot to check the legacy version when I checked if everything still worked after the "references are a real data type now" update...
It's an easy fix at least, remove all the minus signs from setting up the buttonevent array and then in the one mouse event in that object (which handles actually clicking the buttons) replace the line 18 "if(bev < 0){" with "if(!is_real(bev)){". I'll get a fix for this up ASAP.
I'm reading your question as "you need to find 2 separate potions to unlock a cutscene" and then you'd do something like,
if(inventory_has_item(FIRST_POTION) && inventory_has_item(SECOND_POTION)){
csc_enqueue( ... ) //stuff from the good cutscene where you cure the sick grandma)
}
else{
csc_enqueue( ... ) //stuff from the bad cutscene where you're told you need to find both the potions
}If it's two of the same potion you'd use inventory_has_item(POTION,2) (it can check for specific quantity)
Fundamentally, all items work the same and the category is just for sorting. You just need to give the key item a validflag for using in field, a use_script and an use_arg and it should become usable. The actual functionality would be in the use_script, and if you don't need the use_arg you can just ignore it in the script.
(Check out init_items if that explanation didn't make sense)
For party is full, use amp_get_new_box_id to get a box slot if the party is full (amp_get_new_party_id returns NONE if there's no free slots)
Use msh_spawn_namingmenu to spawn a nickname menu. You can see how it's used in mev_battle_catch_nickname (note how it assigns the my_monster variable to the AMP slot the monster was placed in)
For priority, I would add a new parameter to init_move for move priority (which is 0 for all moves that doesn't have a priority) and then when you action_slate the move, add some big number times the move's priority to the speed-priority parameter. There's three places move-actions are slated: mev_battle_attack_select, mev_battle_attack_select_target, and obj_battlecontrol's step event. (There's already cases where actions are slated with higher priority, like when using a consumable item in battle, so the only thing that's missing is a bonus priority value from the move data)
For "attack heals for a percentage of damage" I would add a new side-effect type called "movespfx_LIFESTEAL" and give to those moves, special effects are handled in obj_battlecontrol's step event (search for "mvd_SIDEEFFECT_TYPE" to find where it's processed) and this is where you'd add the logic to heal the user based on how much damage the target took (the user's ID is in a_user). You can access the amount of damage dealt through n.my_dmg (the obj_damageapply created in the Damage block) though you'd probably want to save it in its own variable that's always initialized to 0 (in case the damage block gets skipped due to the move having 0 power n.my_dmg does not exist which will lead to a game crash if you try accessing it).
For multiple buffs/debuffs i would do something similar, add new side effect types for multiple buff/debuffs, and for these the mvd_SIDEEFFECT_SUBTYPE slot of the movedata would be an array:
[50, movespfx_MULTIDEBUFF, [stat_DEF,stat_RES], 1]
Applying these would be very similar to the current buff/debuff code but you loop over the "stat" value (since it's an array).
...actually, you could probably just turn the regular buff/debuff cases into loops in case an array is passed into them (use is_array to check), and avoid the extra work of having separate multibuff/debuff values.
If you want a Palworld-style instant success when fishing a monster, you can give the player a new monster anywhere you want by getting the first free party ID with amp_get_new_party_id / amp_get_new_box_id and then use amp_generate_monster to fill it with monster data. So when you successfully clear the fishing minigame you'd do this and then show a little announcement about it.
If you instead want to trigger a battle when fishing up a monster, the code in player_step_fill shows how to trigger a random encounter (though you'd probably wanna use a different list of monsters than the area's regular encounter table when picking which monster you fight).
The move list in battle is set up by mev_battle_attack.
I don't understand what you mean with "chosen GUI at the shrine" but the terminal menu is set up by msh_terminal_load_page.
Both of these have comments for what each block of code does (e.g. "Frame with type/MP info") so hopefully it should be easy to figure out how to change the parts you want to change.
Are you spawning the virtual keys offscreen perhaps? All of the menus draw themselves in the Draw GUI event (GUI layer) to avoid having to think about that, be careful not to use the x / y position of menu objects (which is not used) but instead check the coordinates of the GGUI frames / GGUI elements, which are in GUI coordinates.
(Also, are you using the Game Maker virtual keys system or making your own?)