
Yal's Monster Collector Engine
A downloadable asset pack for Windows
Yal's Monster Collector Engine is a GameMaker:Studio 2 project with all the tools you need to make a monster-collector RPG in the style of Pokémon / Digimon / Temtem / Telefang. The turn-based engine is supplemented with a solid database and GUI system that lets you easily script menus and manage data.
Try out the free demo if you want a first-hand taste of all the cool stuff this engine can do! It's got close to an hour of gameplay if you take your time and explore everything! :D
Features
- Define a monster, item, move, or other database item with a single line of code! It's super easy to add content! Items and moves are based on extensible effect structures, and the engine comes with plenty of example items, monsters and moves to play around with!
- Databases are set up using GML scripts - easy to change, and you get tons of color coding by default!
- Each database entry is a single line in the script! All data is in one place, and it's super easy to add new monsters, moves, types and items!
- Non-standard functionality is handled by script references, letting you offload as many complex special cases as you need to elsewhere in the codebase, keeping the database structured and clean!
- Cutscenes uses a similar system where you enqueue script to be executed, each one with as many arguments as is needed! Just enqueueing messages is good enough to get information across, but you can get as advanced as you want!
- Engine back-end code is only using the most basic GML functionality (arrays, loops etc) ensuring maximal compatibility between exports, and making the code easy to read and understand! The code is also fully commented, with special tags to point out clever hacks and other parts that needs handling with care or are sensitive to changes.

- The battle system supports an arbitrary amount of monsters on each side in battle! Do you think 1-on-1 battles is boring? How about making 2-vs-5 battles the new standard! You can have more monsters than fits on the screen if you want!
- Moves, capturing monsters, battles etc handles an arbitrary amount of monsters on each side just fine! You can even set the number of monsters on each side on a battle-per-battle basis, surprising the player with a 6-vs-1 horde battle in the middle of a dungeon for some extra challenge!
- Newly caught monsters that don't fit in your party automatically gets sent to the storage system! Easily move monsters around between the active party and a number of storage boxes! (The number of storage boxes also can be set to any number you want - default 10 boxes of 40 monsters)
- Supports as many savefiles as you want! (Default 99)
- Easily set up monster trainers and other NPCs right in the room editor using the new GMS2 "variables" system! You don't even need to open a code editor, you just provide some monster data and dialogue data and then it's all set!

- The engine automatically keeps track of both items and trainers! All you need to do is place them in a room, and the game will register them as defeated / collected automatically!
- Simple system to connect different rooms with doors - doors just use two variables: a "label", and a room to transport the player to. The player is automatically placed next to the door with the matching label! Give your doors clear names like "shrine" or "freddy's house" instead of having to worry about their coordinates with pixel perfect precision!
It's Super Effective!
- Traditional mechanics like move types being effective against certain monster types, held items having special effects, and monster trainers fighting you with a series of extra-strong monsters all are in place, and will work out of the box!
- The held-item system has hooks set up at several points in the combat-turn flow, allowing you to run a script there to do whatever you want! Power up a monster's attack, heal it at the end of a turn, react to an enemy's attack, and more!
- The type system allows an arbitrary number of types with extra damage, weakened damage, or downright immunity to other types! Add in that type you always wanted in the ultimate clash of elements, or settle down for a simple system that literally uses rock, paper and scissors!
- Catch feral monsters, level them up, and watch them learn moves and even transform into new stronger species!
- Monsters can automatically transform into a stronger species when their level is high enough! You just need to define the bond in the monster database, the engine handles the rest!
- Monsters learn new attacks automatically, you just need to define it in the monster database!
- Give your monsters nicknames to make them more relatable! Won't change anything gameplaywise, but it sure is fun!
- The GoodGUI System from Yal's SoulsVania engine makes a return, making it easier than ever before to script your own menus! Plot out frames and fill them with content, and the menu contents will stay in position even if you resize the frames later! No need to manually tweak every coordinate to pixel precision!
- Want to make a traditional RPG but feel RPG Maker is too limited? Just dummy out the monster-catching part and you've got a powerful turn-based battle engine to play around with!
- Comes with graphics, music, sound effects, and monster data that can be used commercially! Use the engine for whatever you want, as long as you don't resell it (or parts / derivative works of it) as an asset pack!
(Note that this project is not compatible with GameMaker Studio 1.x)
Try it out!
There's a free demo of the project showing off all the features! Explore the first area, pick a starting monster, catch and train a party of local fauna, take in the tranquility of Driftwood City, and rise to the challenge of Fielder, the first League Master!
Demo controls:
Arrows - Move around / select stuff in menus
X - Select stuff / interact
Z - Cancel
Purchase
In order to download this asset pack you must purchase it at or above the minimum price of $7.49 USD. You will get access to the following files:
Download demo
Development log
- Small bugfix: GMS2 ver.3Jul 19, 2024
- Bugfix: crash when using Unnerve after the 2022.11 runtime ID overhaulDec 29, 2022
- Source code GMS2.3 (fixed): small bugfixAug 16, 2021
- Source code v.2: minor bug fixJun 06, 2020














Comments
Log in with itch.io to leave a comment.
Hi Yal, during battle, if I have seperate animations designed for a specific monster, like idle, phys/mag/stat moves, and hurt animations, how would I change the animation state, instead of the current hard coded animation?
Also how do I make it so when a monster use a certain type of move it will play one of the three pre-done animations?
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)
Thank you so much! I'll try it out.
Me again yal haha, how about sistem like mega evolution. Can you give me the easy way to add it in this engine
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.
Another hehe, what var map mean in init_monsters script. If no use, can i use it to numbering the monster ini the dex?
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")
Thanks yal, two other questions again. First How to add monster owning sign at monster encounters and second how to add number sign of monster enemy trainers has in his party
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)
Thanks yal, another one how to add split evolution easily. Either with item or level
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)
Me again 😁, how about TM. How to add it easily?
I'm thinking something like this:
Hai y al, me again, i want to change the player overworld sprites size to 32x32 and the tileset to, can you guide step by step so i can change it without problem on the engine. Also are this action safe?
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.
Hey yals, i think i touch very important code in this engine. Maybe at priority of message script. Hmm 😢😥😭
___________________________________________
############################################################################################
ERROR in action number 1
of Destroy Event for object parent_menu:
Unable to find any instance for object index '49' name 'obj_player'
at gml_Script_csc_proceed (line 5) - obj_player.my_sprite = spr_player
############################################################################################
gml_Script_csc_proceed (line 5)
gml_Script_mev_messageproceed_script (line 6)
gml_Object_parent_menu_Destroy_0 (line 6)
gml_Script_message_menu_step (line 5)
gml_Object_parent_menu_Step_0 (line 10)
Can you help me?
The error is because there's no player in the room. One way around it is to use with loops instead which does nothing if there's no object that matches it, try replacing the line with this:
with(obj_player){ sprite_index = spr_player; }Hey yal. Me again, how to use key item. I need to use spesific key item so I need to call variable to that specific key item to use in script
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)
oh okey, can you give me example code that check if i have a 2 potion in my inventory to perform a script
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)
thanks yal, finally work
Pertanyaan lain, bagaimana cara mengatur item spesifik yang hilang setelah digunakan dengan cara yang sederhana? Saya masih belum mengerti skrip kehilangan item inventaris. Terlalu rumit bagi saya.
nevermind fix it 😀
Hallo Yal! Just a general question, how would I go about making special move effect logics in a relatively simple way? Such as incorporating move priority, attack heals for a percentage of the damage, or (de)buffing more than one stat at a time, etc.
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:
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.
Hai yal, me again. How to easily add fishing system ini this engine? I mean not only fishing a monster but sometime item to
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).
Thanks yal. yeah it work, but problem come when the party is full. How to fix this? Also monster nickname
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)
i still has problem with this, because I don't understand which script i used first, get monster to the party or rename it? Can you give me the example code?
thank yal but it fix now, i just need script to check empty party and box now
Another question, i tried to change the size of monster move bar gui at the battle but i cant find it how. Same happen with chosen gui at the shrine. Can you guide me how?
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.
Thank yal fix the gui battle move, but the gui i mean in the shrine was dialog box that pooped with option such as heal and other. I wanna to change that to
Ah, got it.
Currently it uses the cc_question cutscene command (which is shared between all multichoice questions) so my recommendation would be to copy that to a new script cc_shrinequestion and then edit that to create the menu the way you want.
Hei. Me again, what is the best way to add virtual key at this engine. I try but sometime they vanish at some place
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?)
Any plans to update any further? Like add more features and such?
Not really, adding more features also makes it more complicated to use. (Though if you check the comments I have suggested implementations for a lot of commonly requested features)
Hey Yal can you help me with making abilities so far i have initialized them the same way you have monsters and items, but i cannot seem to understand how those work also i am having trouble drawing them in the status menu, how do i do that.
So far i have done this :
function init_ability(argument0, argument1, argument2, argument3, argument4, argument5, argument6 ,argument7) {
global.ability_data[argument0,abl_NAME ] = argument1
global.ability_data[argument0,abl_TRIGGER ] = argument2
global.ability_data[argument0,abl_TARGET1 ] = argument3[0]
global.ability_data[argument0,abl_CHANCE1 ] = argument3[1]
global.ability_data[argument0,abl_TYPE1 ] = argument3[2]
global.ability_data[argument0,abl_EFFECT1 ] = argument3[3]
global.ability_data[argument0,abl_SEVERITY1 ] = argument3[4]
global.ability_data[argument0,abl_TARGET2 ] = argument4[0]
global.ability_data[argument0,abl_CHANCE2 ] = argument4[1]
global.ability_data[argument0,abl_TYPE2 ] = argument4[2]
global.ability_data[argument0,abl_EFFECT2 ] = argument4[3]
global.ability_data[argument0,abl_SEVERITY2 ] = argument4[4]
global.ability_data[argument0,abl_WEAKNESS1 ] = argument5[0]
global.ability_data[argument0,abl_WEAKNESS2 ] = argument5[1]
global.ability_data[argument0,abl_WEAKNESS3 ] = argument5[2]
global.ability_data[argument0,abl_IMMUNITIES1 ] = argument6[0]
global.ability_data[argument0,abl_IMMUNITIES2 ] = argument6[1]
global.ability_data[argument0,abl_IMMUNITIES3 ] = argument6[2]
global.ability_data[argument0,abl_STRENGTHEN1 ] = argument7[0]
global.ability_data[argument0,abl_STRENGTHEN2 ] = argument7[1]
global.ability_data[argument0,abl_STRENGTHEN3 ] = argument7[2]
}
/// init_abilities()
function init_abilities() {
init_ability(abl_FLAMECLOAK, "Flame Cloak", EMERGE,
[movetarg_USER, 100, type_FIRE, ailment_BURN, 1],
[NONE,NONE,NONE,NONE,NONE],
[NONE,NONE,NONE],
[NONE,NONE,NONE],
[NONE,NONE,NONE]
);
}
#region//ability region
#macro abl_NAME 1
#macro abl_TRIGGER 2
#macro abl_TARGET1 3
#macro abl_CHANCE1 4
#macro abl_TYPE1 5
#macro abl_EFFECT1 6
#macro abl_SEVERITY1 7
#macro abl_TARGET2 8
#macro abl_CHANCE2 9
#macro abl_TYPE2 10
#macro abl_EFFECT2 11
#macro abl_SEVERITY2 12
#macro abl_WEAKNESS1 13
#macro abl_WEAKNESS2 14
#macro abl_WEAKNESS3 15
#macro abl_IMMUNITIES1 16
#macro abl_IMMUNITIES2 17
#macro abl_IMMUNITIES3 18
#macro abl_STRENGTHEN1 19
#macro abl_STRENGTHEN2 20
#macro abl_STRENGTHEN3 21
#endregion
I think the easiest way to figure out how to implement abilities would be running a search (Ctrl+Shift+F) for itemvalidflag_AUTO_, this should bring up all the places where items are automatically triggered (e.g. the Spiked Shell being triggered on damage to deal a counter attack... you'd want a similar check for abilities being triggered on damage at basically the same place, for things like Flash Fire, Sturdy and so on; other abilities might trigger on each turn, or when attacking, etc)
You'll also need to actually give abilities to monsters (so init_monster needs to take a new argument for ability, the global.monster_data array be extended so it can fit this new data in, and the giant setup in init_monsters should provide it of course)
To show the ability, mev_pause_monsters_status is the script that builds the status screen. You'd read out the abl_NAME field here and create a ggui_element_text to display it somewhere.
Hey Yal, can you help me with a few things :
1.How can I delete save files
2.How do i enable double battles for certain trainers
3.How do i set encounters for the room, i found ects_placeholder() but I could not find out how it applied and how to make more
thank you
1) Savefiles are found in AppData/Local/<name you saved the GM project under>, monster_save0 is the first file, monster_save1 the second and so on. It's a hidden folder so the easiest way to find it is to type in %LOCALAPPDATA% in the file explorer path and hit enter.
2) The important part is setting global.player_side_monsters and global.enemy_side_monsters to 2 (that's what controls how many monsters each side is allowed to have at once). The easiest way to inject this would be to copy obj_npc_trainer and cc_battlestart_trainer to new obj_npc_doublebattletrainer/cc_battlestart_doublebattletrainer which are mostly identical but sets these to 2 instead of 1 before the fight starts. (Also note that cc_battlestart_trainer actually can take an array of trainer data, global.encounter_trainer_data has one entry per trainer, so if you want a double battle against specifically two different trainers (instead of an entity like 'twins') you could populate this twice with different monster, dialogue etc data for each trainer.
3) Use an obj_encounterzoneselector, place one in the room and stretch it out over the area you want the battles in and then select the ects_* script with that room's settings (there's two more ects_* scripts with the first town / Driftwood Forest encounter data). They're tied to these markers so you can make things more granular (e.g. have different encounters in different terrain)
Hey yal, i have some trouble when adding another gym leader. Can you help me step by step, i cant figured how to handle badges after winning the battle
Badge status is handled by the array global.player_badges. The first badge is badge 0, the second badge 1 and so on.
You can check cis_leader1 and cis_leader1_beat for an example how this is done:
csc_enqueue(cc_obtainbadge,0)
so for a second badge, you'd instead obtain badge 1 in the same way.
Hey,
I have been working to get evolution items into the game. I have them working, for the most part. You can select it from the items menu, and then use it on a monster, who will evolve if they have an item based evolution that matches the used item. However, once the evolution ends and the room fades out, the game crashes and I'm not quite sure how to fix it. Here is the crash message:
Here is the code of the evolution item:
///itemuse_evolution(amp_id,EvoItem) function itemuse_evolution(argument0, argument1) { var monamp = argument0; var monid = global.active_monster_party[argument0,amp_MONID]; var nevo = NONE; for(c = 0; c < global.monster_data[monid,mond_TOTALEVOLUTIONS]; c++) { if(global.monster_evolution_type[monid,c] == evotype_ITEM) { show_debug_message("Evolution type equals item") if(global.monster_evolution_arg[ monid,c] == argument1) { nevo = global.monster_evolution_mon[ monid,c] inventory_lose_item(my_item,1) ds_queue_enqueue(global.pending_evolutions_queue,[monamp,nevo]) room_goto_fade_dontdestroy(rm_evolution,60) break; } } } if (nevo == NONE) { msh_itemuse_show_party_effects("It wouldn't have any effect.") } }I feel like I must be missing something about the room_goto_fade_dontdestroy function, but I don't know what. Any help would be appreciated. If you need any more details, let me know.
-12341 is the value of the NONE constant (one of the reasons I picked that number was to make it instantly recognizable). You need to set global.load_room to the current room before changing to the evolution room (and also the global.load_x, load_y and load_direction variables to the player's current x / y / drawdir respectively) otherwise it doesn't know where to put you back - and that's exactly what's happening right now.
(For an example of how to do this, check out player_step_fill which handles the "steps in tall grass to the next random battle" counter, and which sets these before changing to the battle room if an encounter is triggered - side note, this function would also be where you put things like "monsters in daycare gets EXP" and "countdown to eggs hatching" happening)
I tried to edit it can you share a video link to where I can just edit the source code, all of it, I search online can't find a code edit video for game maker
Here's the official GameMaker tutorial series on the code editor. (I recommend using GML Code since Visual doesn't really make things easier, just prettier to look at.)
Thank God Oh I needed this so badly, I love the Pokemon engine you made, in fact I truly think it should get more coverage so many people are desprate for one & your is right here. I will definitely watch this
@Yal 🤔 So by “League Master”, is that another way of saying “Gym Leader”?
Since there's only one boss in the demo Fielder might as well be the champion. 😉
[total-mhp-atk-def-mag-res-spd] What does total mean? I get all the others but Idk why total is there
Total is the actual number of stat points, it gets subdivided proportionally over the stats (so the mhp-atk-def-mag-res-spd values are relative - e.g. if ATK is twice as high as DEF, the final stat will also be twice as high, but the actual value that gets stored in the end is TOTAL x ATK/(sum of all 6 stats), not ATK as-is).
The reason for why it's this convoluted is so it's easy to balance monsters - if two monsters has the same stat total, they should theoretically have the same power. (You can see this in Pokémon where there's tiers like "pseudolegendary" (600 stat total), the games never draw attention to this but competitive play communities does and that's where I got the idea originally)
Hello,
With the current logic in a battle with 2v2, if you select to attack 1 monster with both of your monsters and if the first attack kills the selected monster, the attack from the next monster will 'miss' and say 'there is no target'.
Is there a simple way to update this logic so that if another monster is still alive on the enemy side it attacks that monster instead of missing? Kind of like a 'check for other alive enemies first before missing' function.
Thanks
The part which applies the move is the part (starting at line 671) which begins:
//Apply to all target(s) individually for(var c = 0; c < array_length(a_targ); c++){Currently it doesn't do anything special to detect targets not existing, it checks if the number of hits is 0 and the number of misses is also 0 to conclude that there was no target after the fact. (Done immediately after this loop)
So what I'd do is insert a check before this loop, which checks if the original target remains, otherwise gets a random one based on the move (using the function enemies use to pick random targets):
found_targets = 0; for(var c = 0; c < array_length(a_targ); c++){ var trg = a_targ[c]; if(battle_is_alive(trg)){ found_targets++ } } if(found_targets == 0){ a_targ = battle_get_random_targets(a_user, a_comm); }Perfect thanks! Works like a charm :D
Hello!
I was wondering if I could discuss a commission based on this engine? Please email me at squidbatgamesllc@gmail.com if you'd like to discuss this in more detail.
Hello!
I don't really do commissions, I'm afraid - I barely have time to bring my own ideas to life :P But if you're stuck on anything with the engine, leave a question in the comments and I'll reply to it within 24 hours.
Hi Yal, thank you so much for making this engine, making my childhood dream of making a monster collector game possible!
Recently I discovered a bug where when interacting with anything that opens a dialogue box (npcs, signs, chests, etc), it instantly reactivates once the dialogue is complete. The only way to 'get out' of an interaction is to hold down an arrow key that turns the player away immediately after the interaction ends.
I am still a beginner at coding, so I'm sorry if this seems like a silly question. I have tried messing around with deactivation alarms and checking the interaction scripts, but nothing worked.
One thing I did notice is that in the free demo version of the game there's no such issue. Could it be my GMS version? Currently, I am using the newest Version 2024.06.2.162
I tried it out and also can see it, so something has changed with GM's processing order that causes this (it was always a bug but it just didn't happen before for some reason, lol - presumably the player was always handled before the dialogue boxes but now it's handled after and thus retriggers the interaction immediately after it closes)
It's easy to fix at least, just update the "Interacting" block of obj_player's step event like so:
//Interacting if(interaction_cooldown){ interaction_cooldown-- } else{ if(k_a && !p_a){ var o = collision_circle( x + lengthdir_x(TILESIZE,drawdir) - TILESIZE*0.5, y + lengthdir_y(TILESIZE,drawdir), 12, parent_interactible,false,true ) if(o > 0 && instance_exists(o)){ interaction_cooldown = 5 with(o){ if(object_index == obj_npc || object_is_ancestor(object_index,obj_npc)){ drawdir = (other.drawdir + 180) mod 360 } if(interact_script != NONE){ script_execute(interact_script) } } } } }Then just initialize interaction_cooldown to 0 in the Create event and everything should work as expected.
Thank you for the solution!
Hey, I've been looking to create a monster collection game, and this looks like it might be a great base to start with, but I had some questions. I'm planning on using a simplified grid battle format, so battles would take place across a 4x3 grid. Is this something that would be implementable without absolutely tearing the code base apart? There are a fair number of other changes I would be making to the traditional battle system as well, including creatures being able to potentially learn more than four moves, moves that can be powered up, and more, but I think the grid is the biggest change. Is this engine flexible enough to handle those sorts of large system changes, or would I be better off starting from scratch (or with a different engine)? Either way, this seems like a great engine, it's really cool to see something like it created to help others.
Yeah, all of the grid stuff will need to be custom-made, because there's no concept of positioning and ranges in the engine currently.
What I'm thinking will need to change:
Thanks so much for all the info! Looks like it should be manageable and a good place to get started.
Hey, can I ask what you changed inside of tsprintf, for your 2.3x fix please? I had to import an older version in. This is what I currently have, thank you:
///tsprintf(format,...)
function tsprintf() {
//Trivial String Print Format
//Replaces each % percent sign with an argument, then returns the string.
//Inteded to make writing debug printouts less painful.
var c;
for(c = 1;c < argument_count;c++){
argument[0] = string_replace(argument[0],"%",string(argument[c]));
}
return argument[0];
}
The change was to not modify argument0 directly, but to use a helper variable to hold it (I don't remember what the compilation error was but presumably argument is read-only after 2.3)
The current version looks like this:
///tsprintf(format,...) function tsprintf() { //Trivial String Print Format //Replaces each % percent sign with an argument, then returns the string. //Inteded to make writing debug printouts less painful. var c, s = argument[0]; for(c = 1;c < argument_count;c++){ s = string_replace(s,"%",string(argument[c])); } return s; }Thank you very much for the reply, I really appreciate it. Hey what generation of Pokemon would this be like, Gen 2?
There's enough differences that there's not a 1:1 mapping (partially for legal reasons). If I had to narrow it down I'd probably say "gen 3" because there's support for 2v2 battles (and horde battles) which weren't around in the GBC days.
Oh that makes sense. Thanks again for making this, it's an awesome engine!
Hey :P just wanted to confirm if it was ok to use this engine in a commercial game or not because I've seen a couple other games that are and I love how this one is set up. I'll be making everything else myself, I just would love the ability to skip the code part of it and get right into the creatives
Of course you can! It's even mentioned in the store page description. The only thing you're not allowed to do is resell it as an asset pack, anything else is fair game, commercial or otherwise.
(And just for the record you are allowed to use all of the sprites/music that comes bundled with the code in a commercial game as well, though since a lot of it are placeholder-ish I can see why you'd wanna replace them :P)
How do you make it so only the monsters that entered the battle will get exp?
How do you make in battle the move you used next time you are on the same move? So that when next turn can just press x twice in a row to do the same move again?
Both of these will need you to track some additional data, I think two global arrays with AMP_PARTYSIZE_ACTIVE slots will be enough: global.party_was_in_battle and global.party_last_move_selected.
if(obj_battlecontrol.action_monster.amp_id < AMP_PARTYSIZE_ACTIVE){ switch(global.party_last_move_selected[obj_battlecontrol.action_monster.amp_id]){ case 0: menuvalue_x = 0 menuvalue_y = 0 break; case 1: menuvalue_x = 1 menuvalue_y = 0 break case 2: menuvalue_x = 0 menuvalue_y = 1 break case 3: menuvalue_x = 1 menuvalue_y = 1 break } }Thanks! I got the move to remember which one it uses. I almost got the part with exp. I just it to only give exp to each individual monster based on which one they went against. How do you get for the ID of the opposing monster? So like if it's the first monster they sent out or the second.
if amp_id == 412 { for (var i = 0; i < array_length(global.exp_to_grant_in_battle_to_each_monster); ++i) { if global.party_was_in_battle7[i] == true { global.exp_to_grant_in_battle_to_each_monster[i] += ceil(exploot);}}}Code I think will work to check which ones where in the active at the right time:
if opposingMonsterID == 0 { global.party_was_in_battle1[amp_id] } if opposingMonsterID == 1 { global.party_was_in_battle2[amp_id] } if opposingMonsterID == 2 { global.party_was_in_battle3[amp_id] } if opposingMonsterID == 3 { global.party_was_in_battle4[amp_id] } if opposingMonsterID == 4 { global.party_was_in_battle5[amp_id] } if opposingMonsterID == 5 { global.party_was_in_battle6[amp_id] }How would I get the player monster level and the opposing monster level in obj_battlemonster: Step? Something like this?
The enemy amp_id's start at AMP_FIRST_ENEMY and then go upwards from there, until they end at AMP_FIRST_ENEMY+PARTYSIZE_MAX_ENEMY.
So the first monster that was sent out is in global.active_monster_party[AMP_FIRST_ENEMY], the second is in global.active_monster_party[AMP_FIRST_ENEMY+c], and so on.
(IDs that don't have a monster in them has an amp_MONID of NONE, otherwise amp_MONID contains the monster ID and amp_LEVEL the level)
(PARTYSIZE_MAX_ENEMY is 12 by default but if you use the constant to figure out how long arrays you need it should work out regardless)
Thanks! I got the exp for only the monster who was in the battle working.
Bug: When using a item like a potion on the overworld, if you use it on a monster and hold right or left it will scroll the items 30 times a second(You can hear it scroll like crazy).
How would I make when I use a item on the overworld the screen would stay on the monster select thing instead of closing that and going to the items menu?
The script that applies the selected item is mev_pause_items_use_actually_use, in that you'd want to remove this code at the end which destroys the current menu and the preceding one (the "use/throw away/hold" menu):
I don't see the buggy behavior in the engine source file (ggui_menu_handle also has a check that only runs the left/right handler if you've allocated a menu that's 2 at least slots wide so it shouldn't even attempt to move the cursor in the monster menu which is fully vertical) so it might be something you've changed?
How do you add monsters to your party in the function that gives you lots of stuff to the inventory? Like adding one to the box and stuff?
You can find the code for it in the mev_intro_starterselect_confirm script:
If you wanna add it to the box instead, use amp_get_new_box_id to get the first free box slot instead of the first free party slot.
Two bug reports. In a wild encounter you can mash the x button to make the wild encounter attack before you can do anything. Also when you press the escape button in a wild encounter you can mash the x button to make it press it over and over again only when the first time you escaped.
I'll look into it, probably it can be fixed by manually altering the "active" variable so the menu ignores keypresses during the fadeout.
Hi Yal! Great job with this engine. Love the battle engine! i had a Q. How can i equip the Player with all the available Monsters in his party at the start of the game?
Easiest way would probably be to edit cis_intro_part2 and swap out the cc_intro_startermonsterselect / nickname logic; rather than making a monster choice menu and wait for your input, the startermonsterselect script would instead fill your party with the monsters you want:
First get the ID of the first empty slot in the party, then generate a monster there using its species and level, repeat as many times as you want. There's matching get-first-free-slot functions for the boxes and the temporary enemy slots, too.
To go through every monster like this, rather than hardcoding the monster_id you could loop from 0 to MONSTER_MAX.
Also note that if you really want the player to have every monster in the party, you probably want to increase PARTYSIZE_ACTIVE from 6.
NM I FOUND IT IN CONSTANTS where to put the Macro!
If you haven't found it yet, try middle-clicking constant / function names to immediately open the script file where they're created. Super useful when navigating a large project. (So in this case, you could've clicked any of the monster_ constants to go to the file where they're defined, and that'd been the place to add new ones)
Also the ctrl-shift-F and ctrl-P hotkeys for opening global search / jump-to-asset can be useful if you know something's name but can't find it.
great short cut thank you!
Also it worked! thank you! one last thing. How i can I code so Player can run away from Trainers?
The menu event script for this is mev_battle_escape, you'd just need to remove the special case for trainer battles.
Though you might need to take further measures to prevent the player from immediately ending up in a rematch, cc_battlestart_trainer saves the player's position after they've entered the trainer's vision range. So you'd either need to keep track of a previous position somewhere so you can deposit the player out of harm's way, or maybe give the player a temporary invincibility to further battles after they get away (and while this countdown is ongoing obj_npc_trainer's User Event 2 code - which is where they look for players - will ignore them)
Ok thank you I shall attempt this!
what would be the best way to just remove the trainer from forcing me into a battle. I don't need that functionality in the game i'm building The player would initiate the battle by walking up and pressing the action button.
NM i figured it out! I think i am good to go for now!!! time to start building!~
I completely broke the game adding a room. I deleted it and now player spawns in the middle of the ocean :( Please help.
If you turn on the DEBUG_MODE flag you'll get some helpful printouts in the "Output" window when you load a room (check out the player's Create Event + Alarm 1 event for the code that handles where to spawn).
I think what's happening here is, you saved the game in the now-deleted room, and then when the room doesn't exist anymore the fallback code in mev_title_continue_fileselected which spawns you in the lab might not work anymore if you've changed the layout. (Or if you re-created a room with the same name but a different layout, the saved position will be used but now be in the middle of the ocean)
The door code is in obj_player's collision event with obj_door. But they're meant to be usable without adding any code, instead open the instance in the room editor and check its "variables" window:
Here you select which room to go to and a "label" (whatever text you want), the player is automatically placed at the door object with the same label as the one they entered from. So you can label doors in a town based on which character's house they lead to, and so on. (The code that loads the player based on which door they used is in obj_player's Alarm 1 event)
Not sure why the tileset is so distorted but my theory is that it might've gotten broken if it's got a different size from the existing ones? (320 x 256). Height shouldn't matter but the 320 pixel width is since the tile indices are used for collision checking (left 160px (= 10 tiles) are walkable tiles, right 160px are walls).
Also make sure the tileset settings are correct!
These should also match the grid size of the tile layer you're placing these on (A), re-selecting which tileset to use on the layer (B) will refresh how the tile layer is drawn as well.
Thank you. I figured out your label system early on. I tried to make a room in the indoor and made a door and added a new label. The player would touch the door in overworld and respawn back in the overworld. I didn't know what to do. the next thing i did was use the label of one of the already existing locations in "indoors" and altered the labels of one of the other pre existing indoors. this caused a strange confusion to occur and the tiles were crushed. I then decided perhaps it would be best to make a new room. I copied the room to ensire if there were any game code it would remain intact but upon doing so i destroyed the game. I deleted the room and then repawned in the ocean. I just checked the settings on the tiles and they are correct and also correct in the room. As you are correct the code must be sending me to the ocean of a room that doens't exist however, it has the same sound as the forrest so i think that's where its sending me. How can i fix? I may also try adding the tiles in want to the pre existing tile set provided to see if that works.
i just checked the create event and alarm 1 of the player. I have no idea how to fix.
What I was thinking was, you'd enable DEBUG_MODE (line 5 of init_constants is "#macro DEBUG_MODE false", change it to "#macro DEBUG_MODE true") and then you'll get messages telling you what happens. E.g. if a door transition takes priority, the game will print "Came through a door, jump to LABEL" (so if you're not where you think you are, you can check that the label is correct) and it'll tell you "Player loaded! (room=NAME OF ROOM)" as well so you can tell where you ended up.
You could try adding additional show_debug_message's to e.g. print the player's position after loading, that should make it easier to find in the room editor:
show_debug_message(tsprintf("Player location: %, %",x,y))
As I said before, going through a door will place you at the door with the same name in the other room. So a drawback of this approach is that you can't link two doors in the same room together (because when looping over the door objects it'll find whichever of the two doors with that label is first in the instance list and always pick that). If you want to warp between places in the same room I'd probably create two new objects, "obj_teleport_entrance" and "obj_teleport_exit", which has a label the same way the doors have. Then in player's collision with teleport_entrance, run this code:
var target_label = other.label; with(obj_teleport_exit){ if(label == target_label){ other.x = x; other.y = y; break; } }
Now each teleport pair would use one entrance and one exit. If you want a teleport to be in both directions you'd have entrance A and exit B on one side and entrance B and exit A on the other side; make sure to place the exit some distance away from the entrance (otherwise the player gets stuck in an infinite loop of warping between them).
Are you going to continue working on this soon?
I consider it complete (unless there's a game-breaking bug).
Hi Yal, hope you had a great Summer. I've been trying to setup a 'shop' that displays the monsters seen, and purchase/craft monsters from a list that of them you've caught.
I've taken your UI of mev_pause_moncyclopedia for the shop layout, and am attempting to use the item purchasing goodness from msh_spawn_shop_list and its menu event accomplish this.
The thing I think I'm currently stuck on is using the proper code to set up the var it which I want to be the specific ID of the monster you're hovering over .Then carrying over that info with shop_item variable to the shop menu event.
I've been using it = global.monsters_seen[d] but after starting to use the debug feature, I realized this is not giving me what I need lol.
Here's the code block I'm struggling with to accomplish that. Its the block for the mon's you've caught and thus should be purchasable. I'll link the full script code in a comment below if that helps. Thanks!!!
//Add meta data as well, based on how much info the player has about the monster.
var d, mev, it;
draw_set_font(font_n)//Needed by string_wrap
for(d = 0; d <= maxmon; d++){
vev= d
yy = lerp(0.05,0.95,d/cmax)
hh = lerp(0.05,0.95,(d+1)/cmax) - yy
// ggui_menu_region(0,vev,mev,0.05,yy,0.95,yy+hh)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(global.monsters_caught[d]){
//Wrap flavor text so it fits the box we add below
mev = argument0
it = global.monsters_seen[d] //global.monsters_caught[d]
ggui_fill_meta(0,d,global.monster_data[d,mond_SPRITE_BATTLE],0,global.monster_data[d,mond_NAME],string_wrap(global.monster_data[d,mond_CRAFT_SLOT_SOUL_STRING],VIEW_W*0.6*0.8))
var soul = global.monster_data[d,mond_CRAFT_SLOT_SOUL]
shop_item = it
shop_cost = soul
}
function msh_botsmith_spawn_monsterpurchse_list(argument0) {
//mev_pause_moncyclopedia()
//Make sure statistics are up-to-date
msh_recompute_seencaught()
//Find max monster
var maxmon = 0, c;
for(c = MONSTER_MAX-1; c >= 0; c--){
if(global.monsters_seen[c]){
maxmon = c // maxmon is arraylength
break
}
}
show_debug_message(global.monster_data)
with(instance_create_depth(x,y,depth - 1,obj_gguimenu)){
ggui_menu_preallocate(1,maxmon +1)
//Left pane: monster list (scrollable)
ggui_frame(0,0,VIEW_W*0.4,VIEW_H,spr_messagebox)
ggui_frame_set_scrolling(false,true,1,10,false,true)
var cmax = 10, yy, hh, vev;
ggui_element_text_settings(font_mainmsg,c_white,0,1)
for(c = 0;c < cmax;c++){
vev= c
yy = lerp(0.05,0.95,c/cmax)
hh = lerp(0.05,0.95,(c+1)/cmax) - yy
ggui_element_text_scrollable(0.1,yy+hh*0.5,0,vev)
}
//Add meta data as well, based on how much info the player has about the monster.
var d, mev, it;
draw_set_font(font_n)//Needed by string_wrap
for(d = 0; d <= maxmon; d++){
vev= d
yy = lerp(0.05,0.95,d/cmax)
hh = lerp(0.05,0.95,(d+1)/cmax) - yy
// ggui_menu_region(0,vev,mev,0.05,yy,0.95,yy+hh)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(global.monsters_caught[d]){
//Wrap flavor text so it fits the box we add below
mev = argument0
it = global.monsters_seen[d] //global.monsters_caught[d]
ggui_fill_meta(0,d,global.monster_data[d,mond_SPRITE_BATTLE],0,global.monster_data[d,mond_NAME],string_wrap(global.monster_data[d,mond_CRAFT_SLOT_SOUL_STRING],VIEW_W*0.6*0.8))
var soul = global.monster_data[d,mond_CRAFT_SLOT_SOUL]
shop_item = it
shop_cost = soul
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
else if(global.monsters_seen[d]){
mev = NONE
ggui_fill_meta(0,d,global.monster_data[d,mond_SPRITE_BATTLE],0,global.monster_data[d,mond_NAME],"???")
shop_item[d] = NONE
shop_cost[d] = 0
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
else{
mev = NONE
ggui_fill_meta(0,d,spr_unknownmonster,0,"???","???")
shop_item[d] = NONE
shop_cost[d] = 0
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ggui_menu_region(0,vev,mev,0.05,yy,0.95,yy+hh)
}
//Upper right pane: monster sprite + name
ggui_frame(VIEW_W*0.4,0,VIEW_W*0.6,VIEW_H*0.5,spr_messagebox)
ggui_element_sprite_current(0.5,0.8)
ggui_element_text_settings(font_mainmsg,c_white,1,0)
ggui_element_text_current(0.5,0.8)
//Lower right pane: flavor text
ggui_frame(VIEW_W*0.4,VIEW_H*0.5,VIEW_W*0.6,VIEW_H*0.4,spr_messagebox)
ggui_element_text_settings(font_n,c_white,0,0)
ggui_element_desc_current(0.1,0.1)
//Lowest right pane: total statistics
ggui_frame(VIEW_W*0.4,VIEW_H*0.9,VIEW_W*0.6,VIEW_H*0.1,spr_messagebox)
ggui_element_text_settings(font_nfat,c_white,1,1)
ggui_element_text(0.5,0.5,tsprintf("Species Witnessed: % Species Possessed: %",global.monsters_seen_total,global.monsters_caught_total))
ggui_element_text(0.5,0.8,tsprintf("Required Parts: %",global.monster_data[d,mond_CRAFT_SLOT_SOUL_STRING]))
}
}
global.monsters_caught and global.monsters_seen are arrays of booleans, which means each slot is true if you have caught/seen that monster and false otherwise. In this case you'd just want to carry over the counter itself, since it's the monster ID - so menuvalue_y for the currently hovered item (since it's a vertical menu).
Also, in the moncyclopedia when setting up the events (ggui_menu_region statement) you'll see we give every line a NONE event (which means nothing happens if you press the "accept" button with it highlighted), for your case you'd maybe want to make this conditional - if the monster is available for purchase (global.monsters_caught[d] is true) you'll set up a shop event (which e.g. checks if you can afford the monster and if so proceeds, carrying over the current menu's menuvalue_y as the monster ID the next-level menu refers to), if it's not available (e.g. you haven't caught it yet) you create a NONE event instead.
Thanks Yal! That explains why the monster that keeps getting purchased is Charchne, who is ID no. 1 haha. Could you expand on how I can use these boolean arrays to carry over a counter to properly match the currently hovered mon?
To pass over a value, in the mev_ script you'd do something like this:
with(instance_create_depth(x,y,depth-1,obj_gguimenu)){ daddy = other.id my_monster = other.menuvalue_y //Create frames, elements and events like normal }(Similar to the scripts for doing stuff to party monsters, but instead of referring to the AMP we refer to a raw monster ID)
Hi Yal
Could you help me in the game gun 10 summer, because I have trouble finding a weapon to break the green and blue blocks. I'm currently in Western Flat, after entering the room downstairs where I'm talking to someone there, I can't go back upstairs because the shotgun isn't enough. When, after the fight, the firewall "A" opens, which I go through, and after entering the room, the computer asks for an ID that I don't have and I don't know where to get it. In this room, my shotgun is also not enough to get to the top
What should I do, what am I doing wrong
I am asking you for help
Hi Yal
Could you help me in the game gun 10 summer, because I have trouble finding a weapon to break the green and blue blocks. I'm currently in Western Flat, after entering the room downstairs where I'm talking to someone there, I can't go back upstairs because the shotgun isn't enough. When, after the fight, the firewall "A" opens, which I go through, and after entering the room, the computer asks for an ID that I don't have and I don't know where to get it. In this room, my shotgun is also not enough to get to the top
What should I do, what am I doing wrong
I am asking you for help
Hello again Yal! Do you know if this engine works OK with the most current versions of GM that have come out? I mainly ask because I know there are some retired functions (like arraysize 1D) used. I haven't updated it in forever just in case haha
also a general GM question i'm trying to figure out, I've noticed you use var c for most of you "for" loops. Does that 'c' value get carried over and iterated on in scripts that use multiple 'fors' or is the 'c' reset upon a new 'for'?
Thanks! ^.^
I tested most of my engines with 2023.8 to make sure nothing had broken, I only found a single issue (a missing sprite_exists check in the open world 3D engine). array_length_1d is deprecated but trivial to replace (array_length does the exact same thing) so I figured there's no rush, there's currently no easy way to find a list of all deprecated functions in use in a project so I'd probably just miss something, think the project is safe and then run into a massive tech support nightmare when a new GM update drops anyway.
As for the for loop variable name, I'm just using "c" because there's a programming language called "C++" so writing "c++" as the increment operation is funny. That's the whole reason :P
Anything declared with "var" only exists in the piece of code it belongs to, so c's in different scripts will not affect each other. And with multiple loops in the same script, you reset the variable to 0 at the start of the for loop, so it doesn't matter it's reused. (The exception being when you have a loop inside a loop - then you need separate variables so the inner loop won't mess with the outer loop).
Hey Yal, I picked the engine up a couple days ago and I love it, I have 2 questions and I was wondering if I could get some help or advice.
1. I've redone the move points system to be a pool of points that each move pulls from. I was wondering is there anyway to check to see which side used the attack so the enemy doesn't use the pool of points as well?
2. How does the enemy attack selection work? It looks like it puts all the attacks into a list and then shuffles them around and picks the first one. I was wanting to change it so it's choices are weighted based on mp cost/turn count, so higher mp moves are selected as the fight goes on.
Thanks Yal
1: There's a 'user' field for enqueued actions, for instance the a_user variable in the ctst_TURNQUEUE state in obj_battlecontrol's step event. (this state is probably when you want to consume the points, since it's when the action actually happens). This "user" field is a battlemonster object ID so simply check its side variable: if it's equal to side_ENEMY it's an enemy and shouldn't consume points.
2: Correct, enemies just pick a random move this way (add all valid actions to a list, shuffle it, pick the first option). If you want something priority-based you could rework what happens in the bcontrolstate_ACTIONSELECT_ENEMY segment to use a priority queue instead (ds_priority functions), where you insert things and they're automatically sorted so you can pick the highest priority value - it's pretty much analoguous to how ds_lists work and the only hard part is figuring out how to compute the priorities - you might want to add some new fields to the move database for storing base priority and priority increase per turn to make this easier to control on a case-by-case basis, and maybe rework target selection a bit to account for type matchups (i.e., add every possible move-target combination to the list but multiply the regular priority with the type multiplier for that target)
(Also you might want to still add a little bit of randomness to the priorities, so the AI doesn't become completely predictable and the player can exploit it)
I've also found a bug whereby the game will crash if you try to catch a monster that has already been captured in the same turn, because there is no longer a target. So two player party members, on both party members turn you use a monster ball item, if on the first party members turn the monster is caught, the second party members turn tries to use the monster ball but they can't be captured again, causing a crash. I fixed this by checking in the battle_control before using an item, if the item is a catching item type if the target is still 'alive', and if not, tell the player that it failed etc. If you can replicate might be worth fixing for everyone etc
Oh yeah, might need to have a look into that. I know even the released version of Pokémon Colosseum had a bug which let you duplicate items if you used an item as the first party member and then reordered items on the second party member's turn (so you could get infinite Master Balls that way) so it seems this kind of stuff is tricky to get right.
Hello, another question, how would I go about making it so that the 'box' management makes it so you have to keep two monsters in your party instead of just one? I'm focusing exclusively on double battles and don't want the player to have only one monster in their party at any point
You'll need to change the mev_terminal_grab script a bit. This line
if(amp_read_var(AMP_FIRST_ACTIVE,amp_MONID) == NONE){should be changed to
if(amp_read_var(AMP_FIRST_ACTIVE,amp_MONID) == NONE || amp_read_var(AMP_FIRST_ACTIVE + 1,amp_MONID) == NONE){and now emptying either of the first two slots in the party (by going below 2 party members) should cancel the operation.
(Also, you probably want to update the message that is printed when this happens to read "2 monsters" instead of "1 monster", a little further down in the script)
I just realized, doing it this way still will cause some issues since grabbing a party monster will move any monsters after it in the party lineup forwards one slot, and the undo overwrites the original slot (so grabbing the first monster when you have only 2 in the party will move the 2nd monster to the 1st slot, then it's overwritten by the undo).
It's probably safer to move the party-amount check to just after line 18 (inside the second "if(menuvalue_x < columns_party){" block), and have the check be something more like this:
var partymons = 0; for(c = 0; c < PARTYSIZE_ACTIVE; c++){ if(amp_read_var(AMP_FIRST_ACTIVE + c,amp_MONID) != NONE){ partymons++; } } if(partymons <= 2){ //Error message code goes here (but without the undo, since we don't always pick up the monster now) } else{ //Regular "pick monster up" code goes here }So basically, disallow even picking up the monster if you don't have at least 2 after the operation.
Thank you. If I'm understanding correctly, this will also mean that the player can no longer 'swap' a monster in the party for one in the box if they have only 2 in the party meaning they will first have to get the monster they want from the box and add it as the 3rd party member, then put the one from the party into the box they don't want, correct?
I actually went about this a different way in the end. I modified the obj_terminalmenu step event so that you can't cancel out of the menu if the party has less than two members and put a warning if so. I remove the 1 party member warning from the grab so that you can freely move monsters however the player wants. I can't think of a reason why this wouldn't work, can you?
This sounds like it should work as well, it doesn't matter if you enter an invalid state as long as you're forced to revert to a valid state before you can close the menu. Just be careful about implementing autosaving, new ways to cancel the menus (etc) so the player can't end up stuck with too few monsters that way.
Yes for sure, I realised as well that there is not a release function in the box menu, at least, not one I can see??? So if that's the case and I implement one, I'll just need make sure that the party + box monsters is greater than 2 before you release a monster 😌. But anyway, big thanks for your help and the engine, has been a little tricky to get my head around some things but its progressing nicely
Hello again Yal! Hope you're having a good summer,
I've been working on a shield system by copying how HP works and changing all the variables to ShieldHP essentially. I'm having trouble figuring out how to get the damage to "jump" over to reducing normal HP after the shield bar has been destroyed. ( I have separate dmgapply scripts for shield dmg and normal dmg below) It seems like the damage is stuck on trying to take from the sheildHP pool even after it has reached zero. Probably some simple thing i've overlooked :) Here's what I'm working with:
//Damage
if(pow > 0){
var dmgdata = compute_damage(a_user,trg,a_comm);
if(sheildcheck >0){
n = instance_create_depth(trg.x,trg.y,depth,obj_dmgapplyshld)
n.my_dmg = ceil(dmgdata[0]*ail_power_multiplier)
n.my_mul = dmgdata[1]
n.my_eff = dmgdata[2]
n.my_mon = trg
n.my_user = a_user
n.my_move = a_comm
n.this_is_an_attack = true
}
//********************
if(sheildcheck < 1){
n = instance_create_depth(trg.x,trg.y,depth,obj_damageapply)
n.my_dmg = ceil(dmgdata[0]*ail_power_multiplier)
n.my_mul = dmgdata[1]
n.my_eff = dmgdata[2]
n.my_mon = trg
n.my_user = a_user
n.my_move = a_comm
n.this_is_an_attack = true
//User might hold an item that improves attack effectiveness
if(battle_item_might_affect_this(a_user.amp_id,itemvalidflag_AUTO_ATTACKING)){
var it = amp_read_var(a_user.amp_id,amp_HELDITEM)
n.my_mul *= script_execute(global.item_data[it,id_USESCRIPT],[a_user.amp_id,trg.amp_id,a_comm],global.item_data[it,id_USEARG])
}
}
}
Thanks!!
The code you posted seems to make sense. The interesting thing here is how you compute sheildcheck, and you didn't include that bit of code...
Also, just to get the obvious out of the way: obj_damageapply still does HP damage and not shield damage, right? (So you didn't accidentally change that one as well when you changed all the variables)
(Also note that your two sheildcheck checks are >0 and <1 so both of them will occur for values between zero and one! Is this intentional?)
trg here is the target monster object and we've already checked that it's alive, so you really only need to check if amp_read_var(trg.amp_id,amp_SHIELDHP) is greater than zero: if so, deal shield damage, else deal regular damage.
Hello again,
I'm trying to make it so that when the cursor is over a move in battle, where the box that shows the type of the move and it's MP, I can add in a sprite to indicate the type. I'm looking in the attached image but I'm not sure what element to use to get it to draw the correct icon (I already have the move data setup with the type icons, I just need to know how to draw it)
gguielt_CURRSPRITE element type (added with ggui_element_sprite_current script) is the icon sprite of the currently hovered item in the menu, this is what you want to use here.
Since the data is filled into the menu using ggui_menu_add_option_text it fills the sprite data with NONE, but you could copy ggui_menu_add_option_text and create a new script ggui_menu_add_option_text_and_sprite that also fills the sprite/image data (the two arguments to ggui_fill_meta that are set to NONE within ggui_menu_add_option_text) using two new arguments at the end, and then use that instead in mev_battle_attack. (There's already the _icontext and _gridimage helper scripts that fills the sprite data, but they also set up the elements so that the image is used directly there in the body of the menu, which isn't what you want for this - we want this new script that fills the icon data but doesn't use it yet)
Ah I see thanks, I'll give that a try