Sep 23, 2018 at 7:43 PM
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1640
Age: 27
Pronouns: he/him
So sometime last week Serri asked me if it was possible to use TSC flags to have entities convert from their vanilla state to custom code and while I could have just given a straight "yes" answer and just gave some 3 lines of code on how to do it, I decided to dust off this "thing" I've had sitting around for the past year that I've never really used and decided to explain how it worked.
Changing entities via a TSC flag is ok for basic things, but what if you wanted to use both entities at the same time? And how would you even have them swap from one thing to another? You could use spawn with alternate direction but that has some inherit limitations with how the game handles it in some entities cases, and making it useless in <ANP is definitively not good.
Now to swap topics to broaden things a bit, there are only 360 entities in cave story (plus some ""hidden"" entities and boss entities/sub entities)
This hasn't ever really been a problem for most people who've wanted to add their own entities to the game simply because there are just so many entities already, and mods don't usually get long enough to need to worry about this problem.
However, resorting to using tile in maps with null entities in maps can get slightly annoying if you need some entities in more than one map, or you don't exactly know how your development cycle is going to go. The last thing you want to do is write your custom code over a Special boss and all those labyrinth enemies just to realize that you want them in your mod at some point later in development.
Also colllabs strike a problem where multiple people are developing things and one of them want to use an entity but another person wants to replace it with some other custom entity. Of course there are ways to work around everything I've stated above, but I'm going to present a slightly better solution.
We're moving the first byte of the entity's flags into npc.directive (a free variable)
What is this doing and what exactly does it mean?
Now we can build a table inside our NPC and have it check this first byte and run a different set of code accordingly.
But wait a second how are we going to set these flags?
With these.
Each of these flags such as solid, Ignore solid, shootable, ect are just on/off switches stores in the npc.flags value, and changing these changes what value our npc.directive holds, and therefore changes what part our table will jump to.
so just pop open your calculator, convert your value form decimal to binary and put in the correct flags
Or you can just pay attention to these two values in BL if you are familiar with hex. (and if you're coding your own custom entities you SHOULD be anyway)
And with that, we write the code that branches off our table we made and place the entities on the map.
now with the appropriate flags checked we boot up the game aaanndd...
nice.
Here's the full code used in the npc, and a mod that shows the stuff in action. Just look at what entity flags are set and what sub-entity is displayed in it's place.
https://www.dropbox.com/s/4jrfasapthbx8jt/NPC Array.zip?dl=0
Now there ARE a few inherit limitations using this method.
#1 For each entity and sub entity, you need to manually assign flags in ASM if you want to use the first bye of the entity flags. You can do this by making each sub entity assign it's own flagdata on spawn if it needs something different than just "0" for everything, or you really really need that one entity to be able to swap between having solid bouncy sides and not (also you need to hook into some sort of TSC to make this happen and running commands for EVERY single entity you want to swap between the states for EVERY map is not ok). Of course it's easier to create a new instance in the table that gives it that property and then have it just go to the rest of the code but hey if you've made it this far and you've understood everything you already know this.... most likely anyway.
#2 You cannot use Vanilla TSC to swap between the sub entities or even spawn them at all... Unless you use my hacked <ANP mod
<ANP npc.directive hack
This does limit you from using <ANPs greater than 1000 in your custom entities though so be mindful of that.
Also with the <ANP npc.directive hack you can just have entities change on the fly with one entity's flags to another without disturbing the flags, but you might have to wait one frame if you code it the wrong way. ok I'm getting a bit far into the weeds now...
#3 you ARE NOT limited to the same tileset as the one the original entity is on. You would think you are but actually what bitmap the entity reads from is placed in the entity's variables!
If you want a list of what tile-set is what just look at BL's npc.tbl editor to see what is what.
So there you have it. Fairly easy workarounds to inherit problems (as long as you know what you're doing with your entity flags) and one more TSC command thing.Go crazy with your PEONS attached to this and you basically have all the entities you'd ever need. Hopefully this helps anyone who wants to use this and especially you Serri for whatever MagCSL things come in the future.
Changing entities via a TSC flag is ok for basic things, but what if you wanted to use both entities at the same time? And how would you even have them swap from one thing to another? You could use spawn with alternate direction but that has some inherit limitations with how the game handles it in some entities cases, and making it useless in <ANP is definitively not good.
Now to swap topics to broaden things a bit, there are only 360 entities in cave story (plus some ""hidden"" entities and boss entities/sub entities)
This hasn't ever really been a problem for most people who've wanted to add their own entities to the game simply because there are just so many entities already, and mods don't usually get long enough to need to worry about this problem.
However, resorting to using tile in maps with null entities in maps can get slightly annoying if you need some entities in more than one map, or you don't exactly know how your development cycle is going to go. The last thing you want to do is write your custom code over a Special boss and all those labyrinth enemies just to realize that you want them in your mod at some point later in development.
Also colllabs strike a problem where multiple people are developing things and one of them want to use an entity but another person wants to replace it with some other custom entity. Of course there are ways to work around everything I've stated above, but I'm going to present a slightly better solution.
Code:
mov al, npc.flags //store first byte of flag data
mov npc.directive, al //move it to npc.directive
xor eax, eax
mov byte npc.flags, al //reset the value of the flags to 0 (what the NPC originally had)
jmp :end_of_code
We're moving the first byte of the entity's flags into npc.directive (a free variable)
What is this doing and what exactly does it mean?
Code:
:NPC_value_set
mov eax, npc.directive
jmp [eax*4+:NPCTable]
:NPCTable
print :NPC0
print :NPC1
print :NPC2
print :NPC3
print :NPC4
print :NPC5
Now we can build a table inside our NPC and have it check this first byte and run a different set of code accordingly.
But wait a second how are we going to set these flags?
With these.
Each of these flags such as solid, Ignore solid, shootable, ect are just on/off switches stores in the npc.flags value, and changing these changes what value our npc.directive holds, and therefore changes what part our table will jump to.
so just pop open your calculator, convert your value form decimal to binary and put in the correct flags
Or you can just pay attention to these two values in BL if you are familiar with hex. (and if you're coding your own custom entities you SHOULD be anyway)
And with that, we write the code that branches off our table we made and place the entities on the map.
now with the appropriate flags checked we boot up the game aaanndd...
nice.
Here's the full code used in the npc, and a mod that shows the stuff in action. Just look at what entity flags are set and what sub-entity is displayed in it's place.
https://www.dropbox.com/s/4jrfasapthbx8jt/NPC Array.zip?dl=0
Now there ARE a few inherit limitations using this method.
#1 For each entity and sub entity, you need to manually assign flags in ASM if you want to use the first bye of the entity flags. You can do this by making each sub entity assign it's own flagdata on spawn if it needs something different than just "0" for everything, or you really really need that one entity to be able to swap between having solid bouncy sides and not (also you need to hook into some sort of TSC to make this happen and running commands for EVERY single entity you want to swap between the states for EVERY map is not ok). Of course it's easier to create a new instance in the table that gives it that property and then have it just go to the rest of the code but hey if you've made it this far and you've understood everything you already know this.... most likely anyway.
#2 You cannot use Vanilla TSC to swap between the sub entities or even spawn them at all... Unless you use my hacked <ANP mod
<ANP npc.directive hack
0x46FFa2
7D 31 8B 45 FC 69 C0 AC 00 00 00 0F B6 88 20 62
4A 00 81 E1 80 00 00 00 74 14 8B 55 FC 69 D2 AC
00 00 00 8B 82 50 62 4A 00 3B 45 08 74 0E FF 45
FC EB C6 81 7D FC 00 02 00 00 74 7D 8B 55 FC 69
D2 AC 00 00 00 8B 45 0C BB 94 62 4A 00 3D E8 03
00 00 7C 08 2D E8 03 00 00 83 EB 04 89 04 13 90
Setting <ANP to 1000 or higher makes it write to npc.directive instead of npc.scriptstate. Incredibly useful for custom NPCS where you want multiple instances with variants while keeping access to all other features.
7D 31 8B 45 FC 69 C0 AC 00 00 00 0F B6 88 20 62
4A 00 81 E1 80 00 00 00 74 14 8B 55 FC 69 D2 AC
00 00 00 8B 82 50 62 4A 00 3B 45 08 74 0E FF 45
FC EB C6 81 7D FC 00 02 00 00 74 7D 8B 55 FC 69
D2 AC 00 00 00 8B 45 0C BB 94 62 4A 00 3D E8 03
00 00 7C 08 2D E8 03 00 00 83 EB 04 89 04 13 90
Setting <ANP to 1000 or higher makes it write to npc.directive instead of npc.scriptstate. Incredibly useful for custom NPCS where you want multiple instances with variants while keeping access to all other features.
This does limit you from using <ANPs greater than 1000 in your custom entities though so be mindful of that.
Also with the <ANP npc.directive hack you can just have entities change on the fly with one entity's flags to another without disturbing the flags, but you might have to wait one frame if you code it the wrong way. ok I'm getting a bit far into the weeds now...
#3 you ARE NOT limited to the same tileset as the one the original entity is on. You would think you are but actually what bitmap the entity reads from is placed in the entity's variables!
Code:
npc.tileset=[pointer+34]
So there you have it. Fairly easy workarounds to inherit problems (as long as you know what you're doing with your entity flags) and one more TSC command thing.Go crazy with your PEONS attached to this and you basically have all the entities you'd ever need. Hopefully this helps anyone who wants to use this and especially you Serri for whatever MagCSL things come in the future.