More entities in Cave Story using sub entities feat. Cave array & Serri

Sep 23, 2018 at 7:43 PM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1637
Age: 24
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.

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.

uN6DQw5.png



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

kYcT5Kg.png


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)

1vL3Znz.png



And with that, we write the code that branches off our table we made and place the entities on the map.

kghfX6Q.png


now with the appropriate flags checked we boot up the game aaanndd...

Ff90u0u.png


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.

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]
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.
 
Sep 23, 2018 at 8:00 PM
Best Cow
"Life begins and ends with Nu."
Join Date: Jun 27, 2013
Location:
Posts: 2635
Age: 27
Thank you so much for this idea, BLink! And yes, as he has stated at the very end, this idea will be very likely used in MaGCSL 2! ^_^
 
Sep 25, 2018 at 9:43 PM
Senior Member
"Ha! Ha! Ha! Mega Man is no match for my Mimiga Man!"
Join Date: Nov 21, 2017
Location: hell
Posts: 235
Age: 17
Ooh should try to do it. :D
 
Sep 27, 2018 at 1:02 PM
Part-Time Perfectionist
CS Beta Content Discord Admin
"Bleep, Bloop, Bleep, Bloop"
Join Date: Dec 26, 2014
Location: the back of their own hand.
Posts: 1599
Age: 121
Hm, I could see you running into conflicts by changing <ANP like that.
Here, I made a new TSC command -- <CND (Change NPC Directive) -- with two arguments (so you also don't have to change their direction). It optimises <ANP and its function and uses most of the spare space.
If you're using a hack to change maximum number of NPCs your exe supports, edit 0x46FF9B and 0x46FFFA to your max NPC count, and 0x46FF96 and 0x46FFF5 to your NPC pointer. (and make sure that you apply this hack after you apply your NPC limit inc. hack, too)
Code:
0x42471F
A1 D8 5A 4A 00 03 05 E0 5A 4A 00 81 38 3C 41 4E
50 75 50 A1 E0 5A 4A 00 83 C0 04 50 E8 C0 D1 FF
FF 83 C4 04 89 45 F4 A1 E0 5A 4A 00 83 C0 09 50
E8 AC D1 FF FF 83 C4 04 89 45 F8 A1 E0 5A 4A 00
83 C0 0E E8 99 D1 FF FF 83 C4 04 50 FF 75 F8 FF
75 F4 E8 1A B8 04 00 83 C4 0C 83 05 E0 5A 4A 00
12 EB 40 81 38 3C 43 4E 44 75 3D A1 E0 5A 4A 00
83 C0 04 50 E8 68 D1 FF FF 83 C4 04 89 45 F4 A1
E0 5A 4A 00 83 C0 09 50 E8 54 D1 FF FF 83 C4 04
50 FF 75 F4 E8 38 B8 04 00 83 C4 08 83 05 E0 5A
4A 00 0D

0x46FF94
53 56 BE 20 62 4A 00 B9 00 02 00 00 69 D1 AC 00
00 00 F6 04 16 80 E1 F4 41 8B 45 08 3B 44 16 30
E0 EA 83 F9 00 7E 29 8B 45 0C 89 44 16 74 8B 45
10 83 F8 05 74 1A 83 F8 04 75 11 31 DB 8B 44 16
08 3B 05 54 E6 49 00 7D 02 43 43 93 89 44 16 4C
5E 5B 59 C9 C3 CC CC CC CC CC CC CC 55 8B EC 51
56 BE 20 62 4A 00 B9 00 02 00 00 69 D1 AC 00 00
00 F6 04 16 80 E1 F4 41 8B 45 08 3B 44 16 30 E0
EA 8B 45 0C 89 44 16 70 5E 59 C9 C3 CC CC CC CC
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
CC CC CC CC CC CC CC CC CC CC CC
 
Sep 28, 2018 at 6:23 AM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1637
Age: 24
Hey this is pretty cool. I was planning on making a hack that let you change all the npc's variables but this is also snazzy.

Thanks for this Zxin. <3
 
Sep 28, 2018 at 7:08 AM
Part-Time Perfectionist
CS Beta Content Discord Admin
"Bleep, Bloop, Bleep, Bloop"
Join Date: Dec 26, 2014
Location: the back of their own hand.
Posts: 1599
Age: 121
a hack that let you change all the npc's variables
Oh yeah -- I have one of those, but it's for personal use only at the moment.
 
Top