Those incredible Eggs

Completed patches for Keen4.
User avatar
XkyRauh
Posts: 1114
Joined: Sun Aug 31, 2003 9:14 pm
Location: San Diego, California

Those incredible Eggs

Post by XkyRauh »

Let's change what the Eggs hatch into! The important thing to keep in mind here is that, due to the way the Keen engine works, you must have the creature-to-be-spawned somewhere in the level, otherwise you will get an "uncached" error. For example, if you want the Eggs to hatch into Mad Mushrooms, you'd better have at least one Mad Mushroom in your level already!

Code: Select all

# What comes out of the Eggs?
%patch $10135 $xx $yy
There's the patch -- and here's the different assignments:
Note that in most cases, if a creature had an animation that makes it "look around," I opted to use that, as the Bluebirds which hatch by default do not immediately begin moving.

Code: Select all

$F4 $1F  #Council Member
$12 $20  #Poison Slug
$A8 $20  #Slug "Slime"
$02 $21  #Mad Mushroom
$20 $21  #Egg (actually a BlueBird, because the egg state is set to 'hatched')
$B6 $21  #BlueBird
$78 $23  #Arachnut (active)
$F0 $23  #Arachnut (stunned)
$86 $24  #Skypest (flying)
$E0 $24  #Skypest (preening)
$FC $26  #Wormouth
$A0 $28  #Cloud (asleep)
$18 $29  #Cloud (moving)
$F8 $2A  #Berkeloid (moving)
$D8 $2C  #Berkeloid's tossed flame (not sure what direction it will head)
$9A $2E  #Inchworm (haha!)
$D6 $2E  #The Foot (!?)
$12 $2F  #Bounder
$20 $30  #Lick (landing)
$E2 $31  #Smirky (a.k.a. Gnosticene Ancient / Red Guy who steals points)
$66 $35  #Mimrock
$1A $36  #Dopefish (burping... will probably require testing)
$92 $36  #Schoolfish 1 (may or may not work)
$EC $36  #Bubble
$64 $37  #Schoolfish 2 (more likely to work)
$A0 $37  #Sprite 
$90 $38  #Mine (not sure which one)
$EA $38  #Princess Lindsay (from an Egg?!)
$34 $3A  #The Wetsuit
Bear in mind that I only tested the Poison Slug, Lick, Mad Mushroom, Princess Lindsay, a Mimrock, and the Cloud.

Princess Lindsay is unable to be interacted with, and just floats straight up... right off the screen. Not very useful.

When you spawn a Mimrock, it places itself on a lower layer than the foreground floor, so it will appear to clip through the ground. I don't know of a way to fix that, at this time.

I couldn't test any others, because I was using the Chasm of Chills, and those were the only creatures pre-cached for that level. :-) If there are any side effects of this patch that I didn't catch, please let me know.

Good luck and happy tweaking!
User avatar
XkyRauh
Posts: 1114
Joined: Sun Aug 31, 2003 9:14 pm
Location: San Diego, California

Now

Post by XkyRauh »

Now we get even more sophisticated with our Eggs. Chances are, depending on what you're spawning, it's going to appear in a strange place. For example, some of your sprites may be larger or smaller, etc.
Certain monsters, like the Arachnut or Poison Slug, are not affected by "gravity" in the game--they just check to make sure they're the correct height off the ground to be able to move. You can witness this hilarity in Keen4 raw by going to the Pyramid of Shadows, luring a Slug onto the switchable bridge, and then flipping it. Instead of the Slug falling into the green gunk, it turns back and forth in midair frantically until you give it the bridge back.

So, in order to get your monsters to "touch the ground" correctly, you're going to have to change the height at which they are spawned. This involves some math, and your 4SPRITES.TXT file.

First, let's check the numbers on your Egg sprite, which is #238. By default, it's:

Code: Select all

238: [3, 0, 20, 21], [0, 2], 1
The two numbers we're concerned with are the Y values (height) of the collision box, as well as any offset in the collision box itself. Those are the second and fourth numbers in the first brackets, and the second number in the second brackets. To be more visual:
238: [3, 0, 20, 21], [0, 2], 1
So subtract the Red number from the Green number (Y2 minus Y1) and you get the height--keep the blue number (offset) in mind only if it is different between the two. In this case, the Egg's height is 21, with an offset of 2.

Now, let's say we're spawning an Arachnut. The Arachnut is #301:

Code: Select all

301: [4, 4, 35, 39], [0, 0], 1
To be more visual, again:
301: [4, 4, 35, 39], [0, 0], 1
So Red minus Green (39 minus 4) is 35, with an offset of 0.

The difference in heights is (35-21) which is 14, plus the offset difference of 2 gives us 16 total. So when the Arachnut lurches out of the Egg, he needs to be set 16 pixels up, so he detects the ground correctly. Hoo.

After all that explanation, we have our patch:

Code: Select all

# How high off the ground do the Egg's contents spawn?
# the default is $80 $00
%patch $10106 $xx $yy
The Keen engine, for whatever reason, does things in fractions of 16. That means that if we want the Arachnut to be 16 pixels up, we need to do (16x16) 256, which in HEX is 0100. Since we have to put our patch in as a 2-byte word, we have to turn 0100 into 01 00, and then reverse it... so our final patch would be:

Code: Select all

%patch $10106 $00 $01
That will let our Arachnut run freely across the ground after he's hatched from his egg. :-)
Kdash
Posts: 405
Joined: Sat Feb 26, 2005 5:45 pm

Post by Kdash »

Aww man, not math!!
This is cool.
About Lindsey - If she was some ghost or something, you could have a haunted level, having ghosts fly up when keen walks past a window or something.
It'd be even cooler if the egg spawned a creature depending on what level it was in, or what sprite it is, or something. That way more things could hatch.

EDIT: You know, I might get into patching again. Now, how exactly do you patch this well? You said something about 'comments' in one post, and i remember this program that andy posted a while back that opened a file, making all these wierd codes appear. Tutorial, please!!
User avatar
XkyRauh
Posts: 1114
Joined: Sun Aug 31, 2003 9:14 pm
Location: San Diego, California

Hmm.

Post by XkyRauh »

A while back, Andy mentioned that he'd been working on decyphering and commenting the ASM code. A few of us emailed him and asked for a copy, and he sent it out. But notice in that thread he said he only wanted to email it once... I don't know how comfortable he'd be emailing it again.

Chances are you could grab a copy from someone else, if you see them online. It's not too hard to figure out, because Andy's comments really help clear everything up--but it is definitely slow, and time consuming. And a lot of the commentary hasn't been done yet. :-)
User avatar
levellord
Crazy pAtChEr
Posts: 1401
Joined: Thu Nov 20, 2003 11:35 pm
Location: NewZealand
Contact:

Post by levellord »

Hmm, I should do something like that; I already know where everything is in Keen 1,but I'm not Durdinic enough to assign specific comments to each piece, except in the case of sprites.
Stealthy71088
Posts: 583
Joined: Thu Mar 17, 2005 11:54 pm
Location: NY

Post by Stealthy71088 »

So what if you managed to spawn two sprites at once, like LL's keen1 patch? Could that somehow be used here so that the egg can respawn itself, and lindsey? If you then combined that with a speed patch on lindsey, you could have the ghosts fly past the window multiple times, without it looking ridiculous.
User avatar
XkyRauh
Posts: 1114
Joined: Sun Aug 31, 2003 9:14 pm
Location: San Diego, California

uh...

Post by XkyRauh »

I'm not sure if it's possible. If I tell the patch to put another egg, it just places a Bluebird--I guess because the "state" of the egg is set to "broken" or something. I'm sure Andy could offer a more detailed reason, but a patch that complex is beyond me. :)
User avatar
levellord
Crazy pAtChEr
Posts: 1401
Joined: Thu Nov 20, 2003 11:35 pm
Location: NewZealand
Contact:

Post by levellord »

My patch simply stops the game from stopping at spawing one sprite; what you want is to be able to spawn to distinct sprites, something utterly different. I have had only minimal luck doing this in Keen 4, for some unknown reason the game doesn't like it, and I'm no Mr Rauh.
KeenRush
Patch Maker
Posts: 1988
Joined: Sun Aug 31, 2003 2:52 pm
Location: Sand Yego
Contact:

Post by KeenRush »

Tell me Xky -- how on garg did you get those enemy values (such as "$FC $26 #Wormouth") and the patch offset for the value 'how hight off the ground egg's content spawns'?!
Nevertheless, this is pretty cool. However it'll take a really long time till I get playing around with this stuff.. (First have to make a Keen 3 mod..)
User avatar
XkyRauh
Posts: 1114
Joined: Sun Aug 31, 2003 9:14 pm
Location: San Diego, California

hehe

Post by XkyRauh »

Here's the method I used, and Andy can come in here and beat me with a stick if I'm doing something foolish:

To find the enemy values, I opened action.doc, which was packaged with the K4 Disassembly. After you scroll down past all the #define Keen_Action statements, you start seeing statements like #define A_Member_Walk and #define A_Slug_Walk ... I'll use the Slug: Here's the whole brick of code for the Slug, from action.doc :

Code: Select all

#define A_SLUG_MOVE		0
#define A_SLUG_POOHING		2
#define A_SLUG_STUNNED		3

ACTION slug_actions[] = {
  /* Slug moving routine */
	/* AZ.2012 */
	{	320,	315,	0,	0,
		1,	8,	64,	0,
		NULL,		K:03EA,		G:1847,
		&slug_actions[A_SLUG_MOVE+1]
	},
	/* AZ.2030 */
	{	321,	316,	0,	0,
		1,	8,	64,	0,
		K:0369,		K:03EA,		G:1847,
		&slug_actions[A_SLUG_MOVE]
	},

  /* Slug poohing routine */
	/* AZ.204E */
	{	322,	317,	0,	0,
		1,	60,	64,	0,
		K:03A6,		K:03EA,		G:419B,
		&slug_actions[A_SLUG_MOVE]
	},

  /* Slug's stunned looks */
	/* AZ.206C */
	{	318,	318,	2,	0,
		0,	0,	0,	0,
		G:16C9,		NULL,		G:1913,
		NULL
	},
	/* AZ.208A */
	{	319,	319,	2,	0,
		0,	0,	0,	0,
		G:16C9,		NULL,		G:1913,
		NULL
	}
};
See how the Slug Moving Routine begins with the /* AZ.2012 */ statement? I used that. Since it's one of those two-byte word thingies, we have to change it from 2012 to $12 $20, but that's it. I just scrolled down through action.doc and typed up all the values that looked interesting. :)

So if we wanted to spawn a Slug which was in the middle of *ahem* "Sliming," we could use $4E $20 ... or, if we wanted the Egg to hatch into an already-stunned Slug, we could use $6C $20, or $8A $20, depending on which look we wanted.
User avatar
XkyRauh
Posts: 1114
Joined: Sun Aug 31, 2003 9:14 pm
Location: San Diego, California

Post by XkyRauh »

Finding out how high off the ground the monster spawned was a little trickier, and actually took some help from Ceilick to figure out. (He complained that his Arachnuts hatching from his eggs weren't moving correctly... and remember, I said I couldn't test it because I couldn't think of any default Keen4 levels with Arachnuts and Eggs in them...)

Looking at the default Egg sprite in 4SPRITES.TXT, its collision box was 21 pixels tall. Looking at the Bluebird, its collision box was 29 tall. So the difference between the two was 8 pixels... and I remembered what Andy said about the engine working with fractions of 16 (as I learned while gumming up this thread with my questions) So 8 times 16 is 128, which in hex is 80.

If you open up notes.txt in the K4 Disassembly folder, there's basically a table-of-contents to the segment files. On the far left, it tells you the letter of the segment file, and on the right it tells you what's in it. Scroll down to the K.Sub section, and near the bottom you can see "void spawn_egg( int x, int y );" which tells us the Egg info is in seg__k.

Open up seg__k and scroll down to the routine that spawns the Egg--and below that, what happens when it hatches. A lot of this part of the code is uncommented (as you can see by the lack of entries in notes.txt) so some of this is just guesswork. Anyway, I found this:

Code: Select all

   K.0673  C7 07 001B                           mov     word ptr [bx], 1Bh
	new_object->type = OBJ_EGG;
   K.0677  C7 47 02 0001                        mov     word ptr [bx+2], 1
	new_object->active = 1;
   K.067C  8B 44 0A                             mov     ax, [si+0Ah]
   K.067F  89 47 0A                             mov     [bx+0Ah], ax
	new_object->xpos = _SI->xpos;
   K.0682  8B 44 0C                             mov     ax, [si+0Ch]
   K.0685  2D 0080                              sub     ax, 80h
   K.0688  89 47 0C                             mov     [bx+0Ch], ax
	new_object->ypos = _SI->ypos - 128;
Now, honestly, I think that the notes there should say "new_object->type = OBJ_BLUEBIRD, because hatching the egg does not spawn a new egg... hehe... but anyway, see that 0080 in the code, and the comment about ypos beneath it? Gold. That's what I wanted to patch. But how to find it?

I opened up my dump.txt file with XVI32, and did a Find command for the hex clumped around that 0080... keeping in mind that every set of 4 numbers in a row (xxyy) is a 2-byte word and therefore would appear as (yy xx) in the hex, I searched for something like:

8B 44 0A 89 47 0A 8B 44 0C 2D 80 00 89 47 0C

That turned up just one hit, all the way through the whole thing. If I'd put in less, I might have got multiple hits, because multiple things in the entire code might have used similar commands and coordinates. Anyway, once we found that string, we just isolate the 80 00, which was at $10106, and then experiment with values. :)

The last comment I want to make about this is that, typically, when I'm working on finding patches like this, I have the following things open:

XkyKeen4 folder, Keen4 disassembly folder, 4SPRITES.txt, XVI32 with dump.txt loaded, one or more seg__*.doc files, Calculator, and XkyKeen4.pat for testing. :) And then occasionally a chat window or two, so I can ask questions to Spleen or Ceilick about what's going on.
KeenRush
Patch Maker
Posts: 1988
Joined: Sun Aug 31, 2003 2:52 pm
Location: Sand Yego
Contact:

Post by KeenRush »

Ah ok -- I didn't know there was stuff documented so well! I should take a better look at those documents.. I haven't read them much, mainly because haven't done anything Keen 4 related. :) Cheers.
User avatar
XkyRauh
Posts: 1114
Joined: Sun Aug 31, 2003 9:14 pm
Location: San Diego, California

Post by XkyRauh »

Hehe.... There's Egg on my face, on this one. The patches here change what the monster looks like, sure, but technically whatever you spawn is still a Bluebird object type, even though it behaves differently. This means that even if you spawn 300 Inchworms using Eggs, they'll never turn into a Foot, because the object TYPE is not Inchworm.

Code: Select all

#Set the object type that hatches from Eggs
%patch $100F5 $zz $00
Here's a largely incomplete list of potential values:
Bubble/inconsequential foreground object that doesn't interact with anything: $01
Commander Keen: $02
Keen's Shot: $03
An item: $04
Poison Slug: $05
Oracle Member: $06
An Egg: $08
Mad Mushroom: $09
Wormouth: $0C
Cloud: $0D
Berkeloid: $0E
Bounder: $0F
Inchworm: $10
Foot: $11
Lick: $12
Platform: $14
Princess Lindsay: $18
Lightning (from cloud): $19
Bluebird/Eagle (default): $1B
Stunned Bounder / Mimrock / Ancient (shot while jumping): $21
Hopefully that'll clear up any confusion with this patch...
Last edited by XkyRauh on Thu May 24, 2007 12:32 am, edited 1 time in total.
levellass
Posts: 3001
Joined: Wed Oct 11, 2006 12:03 pm
Location: Ngaruawahia New Zealand

Post by levellass »

I was simply making the spawned monster use a piece of code that switches its type. (Make the egg hatch a napping Skypest and it will have the skypest type when it hatches.)

This new little tip however is greatly useful...


Also, you have a few object types wrong; $01 is 'Don't affect sprites' $18 is Lindsey, and $21 is 'shot jumping sprite/ (Smirky, Mimrock and Bounder)
User avatar
XkyRauh
Posts: 1114
Joined: Sun Aug 31, 2003 9:14 pm
Location: San Diego, California

Post by XkyRauh »

Alright, I edited my post to include Princess Lindsay. The other two were really semantics. :)
Post Reply