• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Crystal hack: Pok?mon: Stygian Version (vDEMO_0.015 RELEASED!)

What have you done so far in vDEMO_0.013? Please don't select anything if you haven't got the requir

  • I skipped the introduction sequence in the shrine (requires: 5, cannot conflict with 6)

    Votes: 0 0.0%

  • Total voters
    3
19
Posts
11
Years
This's the most creative serious hack I've ever seen o.o I especially like the free capture mechanic. The Shakespearean English is a bit rough, & feels a bit excessive. However, if we're being realistic, nobody picking up a romhack ought to demand perfect 16th century gramar from it. Imo, so long as it looks good to most players, remains understandable & doesn't get old it's good enough.

I'll be looking forward to seeing how this develops ^.^
 

wolfboyft

Pokémon Generation 2 Hacker
165
Posts
9
Years
Interesting concept, I think it has promise and I like the gimmick of free capture.

One thing I feel the need to comment on in this tiny demo is, the "ye olde English" is far too exaggerated. I have nothing against it in theory but it seems you aren't trying to stick to the proper usage of the words. I'm not an expert myself on it, of course, but one thing I do know is you're trying to use thee/ye/thou interchangeably. "Ye" is the plural of "thee/thou" so you shouldn't be using it at all in this case, and the other two are sometimes used correctly and sometimes not.

I apologize if I seem to be a grammar Nazi here, but I feel if you're going to attempt to write like such, you should be aware of how the words you're using were meant to be used.

I like the item system as well, regarding different items having different overworld appearances and knowing what you're taking before you do so.

Lastly, the knight's sprite is good (if I could give a bit of constructive criticism I'd change the shading, maybe remove it on the body plates entirely and instead add some kind of defined decoration, right now it looks like the knight has a belly button on their armor), but I'm not a fan of the goblin sprite, specifically the lack of outline on his shirt. If you added the outline I think it would improve the quality of the sprite.


I don't mean to nitpick, of course, I just thought I'd go a bit in detail since the demo is as short as it is. Best of luck with your hack!

Thanks for the genuine extensively intelligent reply!

I'm just picking up the grammar from Ultima Underworld, I assumed they knew it well. And as for the Goblin, well, there were some technical issues along the lines of graphics compression, but I should be able to do it now. A user I got to make sprites is no longer active, so I made them on my own, by the way.
---

Working on a huge feature right now. It's an action menu. When you interact with any overworld object, a menu with actions comes up. I have to go through an extensively tedious manual process just to integrate it with all the objects I have so far. Ugh. Worth it, though. You can tear up notes, bash money bags and TRY to eat goblins. Oh, and if you're mad, talk to Poké Balls. (What? You said there weren't going to be any Poké Balls! Well, for 'mon that you receive, there ARE.)
 
55
Posts
8
Years
  • Age 28
  • Seen Dec 2, 2021
this is super cool so far. i'm going to make a play-by-play of comments as I go through it

- you can press the button and it says you healed your pokemon... but i don't have any yet! minor but i thought i'd mention it
- the spritework is really nice so far. that boxes are in a weird perspective but that's about it
- the capture mechanic is super cool! and... makes a lot of sense, honestly.

i'll be sure to check again later to see newer versions!
 

wolfboyft

Pokémon Generation 2 Hacker
165
Posts
9
Years
Finally managed to get off my arse (well, get back on it and work on the hack, but you know what I mean) and work on the hack, bumping it up to version 0.009!! YAY! Enjoy the new action menu mechanics.
 

wolfboyft

Pokémon Generation 2 Hacker
165
Posts
9
Years
As someone with a degree in English, I have to stop you here and point out that "ye" is not only the plural of thee/thou. In fact, "Ye" as you are thinking of it is not even a word at all, but just the modern way of spelling more than one old english word, which could have been a pronoun for "you", or could have been "the" as well, depending on which word you're misspelling (the plural was originally written as "ge" when it was actually in use).

The usage of the word "ye" goes back to the medieval printing press. As the printing press was originally created for German text, it did not contain the letter Thorn (þ) which was used in Old English, so printers substituted in the letter Y instead. It looked similar enough that people at the time knew what it meant, the same way people today know that b4 is meant to be pronounced "before" even if it isn't correct. As such, "ye" was meant to be pronounced "the" and was used the same way, it was just meant to be written with a letter we no longer commonly use in modern English.

EDIT: To be real, if it was in correct Old English, nobody here would even be able to read it anymore, because it would go much deeper than swapping a few pronouns. Even if it was more modern, say the English that the Canterbury Tales were written in, most people here couldn't read it. So nobody should expect accuracy in Old English here, and I think going for the same type of wording that the Dragon Warrior games did would be sufficient to achieve the effect.

Quality posting (I hope that's not always taken as sarcastic, because it wasn't meant to be here,) I like it. Good to know. I was going for an approach using Ultima Underworld's standards-- but only consistent.
But don't people in the standard "Dungeons & Dragons" style dwarven culture usually say "ye" phonetically? That's what I'm aiming to include in my hack. I mean, something like "ach, a great boon that'd be if ye did(st?) that." However, if we realise, this hack isn't necessarily set in the real world's universe. At all... so it can have its own history, with its own langauge. Ye art could be fine, here. Although I'd understand anyone who wanted to have proper old english grammar.
But anyway... what're your thoughts on the hack, aside from language?
 

wolfboyft

Pokémon Generation 2 Hacker
165
Posts
9
Years
Holy CRAP, the storage cache room was WA-A-A-AY more bugged than not bugged (which is how bugged I thought it was.) I'll be releasing a hot-fix for all the ridiculous stupidity soon!!
 

miksy91

Dark Energy is back in action! ;)
1,480
Posts
15
Years
Some pretty cool features you have here. Have you considered making it so that when you approach an event and press A, the game would react like you chose to "Talk" to it? Or would that work at all? I take it you have made it so that no script is run when you approach them, or their script pointer points to "end script data".

Anyways, I personally don't see why the text couldn't be in normal english. That would make reading a lot simpler and it's a bit annoying that it's not that way actually - at least for me since I don't even speak native english.
 

wolfboyft

Pokémon Generation 2 Hacker
165
Posts
9
Years
Some pretty cool features you have here. Have you considered making it so that when you approach an event and press A, the game would react like you chose to "Talk" to it? Or would that work at all? I take it you have made it so that no script is run when you approach them, or their script pointer points to "end script data".

Anyways, I personally don't see why the text couldn't be in normal english. That would make reading a lot simpler and it's a bit annoying that it's not that way actually - at least for me since I don't even speak native english.

Paragraph 1: I don't see what you mean. The philosophy behind actions in this hack is that you can do as you like-- within bounds of reason. To make it more interactive, you CAN tear up notes, you CAN poke Moe/Lanugo/Isaac, you CAN take the notes with you-- only problem is that you can't put them back down again. I take it you're referring to the ankh, green goblin, monk and the two banners in the shrine? They do point to an end, yes. For the ones that do work, look at these two code snippets:

Code:
.firstMonActions ;label
	showemote EMOTE_SAD, LAST_TALKED, 15 ;the arrow
	callasm StartMenuSecondary ;my menu script
	if_equal 1, .ATKmon ;attack
	if_equal 2, .TCHmon ;touch
	if_equal 3, .TLKmap ;talk (reuses the one for the "map" (actually note one))
	if_equal 4, .LOKmon ;look
	if_equal 5, .INGmon ;ingest
	if_equal 6, .TKEmon ;take
	if_equal 7, .USEmon ;use
	end ;take a guess

Spoiler:

Paragraph 2: Well... it's heavily inspired by Ultima Underworld, so you can expect it :P
 

wolfboyft

Pokémon Generation 2 Hacker
165
Posts
9
Years
"Magic Scarf" is the name of an item that replaces the classic stick.
It will reduce all incoming damage by 17% when held.

OP much? It's from an extremely difficult optional sidequest boss that I'll add at some point mid-game :)

As for attack... well, ever wanted your Pokémon to hold a magic chainsaw? Sure! Now they can! Increases all damage by 17% (code is run before the magic scarf, if that really makes much of a difference.)

Ever wanted to hold two items at once? Well, you can't do QUITE that, but you can merge the magic chainsaw/scarf together! Awesome. Hotfix/content update is coming, my beautiful people!

Just wait ^^
 

miksy91

Dark Energy is back in action! ;)
1,480
Posts
15
Years
Paragraph 1: I don't see what you mean. The philosophy behind actions in this hack is that you can do as you like-- within bounds of reason. To make it more interactive, you CAN tear up notes, you CAN poke Moe/Lanugo/Isaac, you CAN take the notes with you-- only problem is that you can't put them back down again. I take it you're referring to the ankh, green goblin, monk and the two banners in the shrine? They do point to an end, yes. For the ones that do work, look at these two code snippets:

Code:
.firstMonActions ;label
	showemote EMOTE_SAD, LAST_TALKED, 15 ;the arrow
	callasm StartMenuSecondary ;my menu script
	if_equal 1, .ATKmon ;attack
	if_equal 2, .TCHmon ;touch
	if_equal 3, .TLKmap ;talk (reuses the one for the "map" (actually note one))
	if_equal 4, .LOKmon ;look
	if_equal 5, .INGmon ;ingest
	if_equal 6, .TKEmon ;take
	if_equal 7, .USEmon ;use
	end ;take a guess
What I thought you had done there was that the script pointer of all those items pointed to "end" structure and if you pressed Start while facing an event that is in front of you, it would execute an asm routine that would check, what kind of event is in front of you and open a menu with options based on that.
You seem to have made the "StartMenuSecondary" play the same sound that is played when you press Start. That's why I assumed it also worked like that in the game.
 

wolfboyft

Pokémon Generation 2 Hacker
165
Posts
9
Years
What I thought you had done there was that the script pointer of all those items pointed to "end" structure and if you pressed Start while facing an event that is in front of you, it would execute an asm routine that would check, what kind of event is in front of you and open a menu with options based on that.
You seem to have made the "StartMenuSecondary" play the same sound that is played when you press Start. That's why I assumed it also worked like that in the game.

Ah. Well... you know now :)

Say... could you, with your ASM skills, verify that http://pastebin.com/raw/zqN14NNn makes it so that any Pokémon holding the item "STICK" has all incoming damage reduced by 17 percent? Search for the text...

Code:
; it starts here

...for that is where my code starts. "BattleCommand_DamageVariation" is, in a standard Crystal 1.0 ROM, at the address "0D:4CFD." Not sure if that's little-endian or big-endian, but either way, check that out if necessary.

A guy on the Freenode chat channel #pret gave me most of that code, and then I wrote some, and the rest was from the original pret team's disassembly.
 

miksy91

Dark Energy is back in action! ;)
1,480
Posts
15
Years
You know what sucks... this forum logging you off while writing a message and not getting it posted at all and having to rewrite it again...

Don't unfortunately have time for that now - I was about to leave but that just happened... Anyway, I think I know what you should do so I can reply you back tomorrow. You need to change a little bit but not much.
 

miksy91

Dark Energy is back in action! ;)
1,480
Posts
15
Years
Well - I think there is actually quite a lot to be changed when I re-think about it. I believe what the code until "it starts here" does right now is the following:

1) Loads the value (2-byte val) of current damage in [hMultiplicand] - [hMultiplicand + 2] so that the value in [hMultiplicand] equals 00. This is for storing the damage value elsewhere where we have room for the result of multiplying with a value that could overflow for a 2-byte value.

2) Next in ".loop", we draw a random number between $D9 (0xd9 / 0xff = 85%) and $FF (100%) and store that into [hMultiplier]. And by calling "Multiply", the value in ([hMultiplicand] - [hMultiplicand + 2]) is multiplied by [hMultiplier].

3) In the next step under 'Divide', we divide that value ([hMultiplicand] - [hMultiplicand + 2]) by $FF and store the result in "hQuotient + 1" - "hQuotient + 2" I believe. Now here we have the original current damage multiplied by a random value between 0,85 - 1,00.

4) In the end of the routine, you should load that value between "hQuotient + 1" - "hQuotient + 2" into register pair bc, or possibly back to "CurDamage - CurDamage + 1".

So basically, I would start off my changing the parts under "; No point in reducing 1 or 0 damage." into "; No point in reducing 1 or 0 damage, or if the defending pokemon is not using STICK." So only in the case when the defending pokemon is using STICK, call a subroutine that re-calculates the damage based on the value in "CurDamage" - "CurDamage + 1" so that that value is changed into 0,85 (or 0,83) times of its original value.

(0,83) x 256 is 212,48 so you might as well use 212 changed into hex in the place of $d9 in the routine

Also what comes to ".loop" part, change that so that you don't draw a random number at all. Just load [hMultiplier] with "212 in hex". Then after dividing, you will have that "0,83 * value of current damage" loaded into [hQuotient + 1] - [hQuotient + 2]. Next you either load that value into bc or load it back into CurDamage.

The reason I don't know which one you should do is because the beginning of the routine clearly doesn't do anything with bc

Code:
	ld hl, CurDamage
	ld a, [hli]
	and a
	jr nz, .go
	ld a, [hl]
	cp 2
	ret c
while at the end of the code in implementation of PikalaxALT, you load that value there.

P.S
Code:
	ld a, [hl]
	cp STICK
	ld [hl], a
The third instruction here doesn't serve for any purpose.
 

wolfboyft

Pokémon Generation 2 Hacker
165
Posts
9
Years
Well - I think there is actually quite a lot to be changed when I re-think about it. I believe what the code until "it starts here" does right now is the following:

1) Loads the value (2-byte val) of current damage in [hMultiplicand] - [hMultiplicand + 2] so that the value in [hMultiplicand] equals 00. This is for storing the damage value elsewhere where we have room for the result of multiplying with a value that could overflow for a 2-byte value.

2) Next in ".loop", we draw a random number between $D9 (0xd9 / 0xff = 85%) and $FF (100%) and store that into [hMultiplier]. And by calling "Multiply", the value in ([hMultiplicand] - [hMultiplicand + 2]) is multiplied by [hMultiplier].

3) In the next step under 'Divide', we divide that value ([hMultiplicand] - [hMultiplicand + 2]) by $FF and store the result in "hQuotient + 1" - "hQuotient + 2" I believe. Now here we have the original current damage multiplied by a random value between 0,85 - 1,00.

4) In the end of the routine, you should load that value between "hQuotient + 1" - "hQuotient + 2" into register pair bc, or possibly back to "CurDamage - CurDamage + 1".

So basically, I would start off my changing the parts under "; No point in reducing 1 or 0 damage." into "; No point in reducing 1 or 0 damage, or if the defending pokemon is not using STICK." So only in the case when the defending pokemon is using STICK, call a subroutine that re-calculates the damage based on the value in "CurDamage" - "CurDamage + 1" so that that value is changed into 0,85 (or 0,83) times of its original value.

(0,83) x 256 is 212,48 so you might as well use 212 changed into hex in the place of $d9 in the routine

Also what comes to ".loop" part, change that so that you don't draw a random number at all. Just load [hMultiplier] with "212 in hex". Then after dividing, you will have that "0,83 * value of current damage" loaded into [hQuotient + 1] - [hQuotient + 2]. Next you either load that value into bc or load it back into CurDamage.

The reason I don't know which one you should do is because the beginning of the routine clearly doesn't do anything with bc

Code:
	ld hl, CurDamage
	ld a, [hli]
	and a
	jr nz, .go
	ld a, [hl]
	cp 2
	ret c
while at the end of the code in implementation of PikalaxALT, you load that value there.

P.S
Code:
	ld a, [hl]
	cp STICK
	ld [hl], a
The third instruction here doesn't serve for any purpose.

I know I shouldn't be by now, but I'm confused. Also, changes to the original routine that the devs made aren't top priority right now :P

Could you elaborate on what you think I should do?
 

miksy91

Dark Energy is back in action! ;)
1,480
Posts
15
Years
Try replacing the beginning of the routine (= the following stuff), and everything following it
Code:
; No point in reducing 1 or 0 damage.
	ld hl, CurDamage
	ld a, [hli]
	and a
	jr nz, .go
	ld a, [hl]
	cp 2
	ret c
with

Code:
	ld hl, BattleMonItem
	ld a, [hBattleTurn]
	and a
	jr z, .got_item_addr
	ld hl, EnemyMonItem
.got_item_addr
	ld a, [hl]
	cp STICK
	ld hl, CurDamage
	ret nz ' don't do anything if not holding STICK. [I]See info at the end of routine what the ending state should be like.[/I]

	xor a
	ld [hMultiplicand + 0], a
	ld a, [hli]
	ld [hMultiplicand + 1], a
	ld a, [hl]
	ld [hMultiplicand + 2], a

; Multiply by 85%
	ld a, $d4 ' (= 212)
	ld [hMultiplier], a
	call Multiply

; ...divide by 100%...
	ld a, $ff ; 100%
	ld [hDivisor], a
	ld b, $4
	call Divide

; ...to get 0.83 damage
	ld a, [hQuotient + 1]
	ld hl, CurDamage
	ld [hli], a
	ld a, [hQuotient + 2]
        ld [hl], a
        ret ' ??? (either try just returning, or loading b with [CurDamage] and c with [CurDamage + 1])

The reason I'd say that you have to do this is because the routine you have there is for multiplying current damage by a value between (($d9 - $ff) / $ff) which makes it 85% - 100% of the original value. So you of course need changes to that part then. Also, in case you're wondering what that "xor a" there stands for, it is actually instruction "xor a, a" and stores the result in a. When you xor a value with itself, the value turns into 0 (or here $00 because we have 8-bit registers). https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/xor.html

Basically, that instruction there simply performs "ld a, 00" but takes one byte less. You'll see that often in GB/C code.
In case there is something else that confuses you about the code, feel free to ask. That just popped in my mind that it might not make any sense what that is for and makes the routine feel confusing.
 
Last edited:

wolfboyft

Pokémon Generation 2 Hacker
165
Posts
9
Years
Try replacing the beginning of the routine (= the following stuff), and everything following it
Code:
; No point in reducing 1 or 0 damage.
	ld hl, CurDamage
	ld a, [hli]
	and a
	jr nz, .go
	ld a, [hl]
	cp 2
	ret c
with

Code:
	ld hl, BattleMonItem
	ld a, [hBattleTurn]
	and a
	jr z, .got_item_addr
	ld hl, EnemyMonItem
.got_item_addr
	ld a, [hl]
	cp STICK
	ld hl, CurDamage
	ret nz ' don't do anything if not holding STICK. [I]See info at the end of routine what the ending state should be like.[/I]

	xor a
	ld [hMultiplicand + 0], a
	ld a, [hli]
	ld [hMultiplicand + 1], a
	ld a, [hl]
	ld [hMultiplicand + 2], a

; Multiply by 85%
	ld a, $d4 ' (= 212)
	ld [hMultiplier], a
	call Multiply

; ...divide by 100%...
	ld a, $ff ; 100%
	ld [hDivisor], a
	ld b, $4
	call Divide

; ...to get 0.83 damage
	ld a, [hQuotient + 1]
	ld hl, CurDamage
	ld [hli], a
	ld a, [hQuotient + 2]
        ld [hl], a
        ret ' ??? (either try just returning, or loading b with [CurDamage] and c with [CurDamage + 1])

The reason I'd say that you have to do this is because the routine you have there is for multiplying current damage by a value between (($d9 - $ff) / $ff) which makes it 85% - 100% of the original value. So you of course need changes to that part then. Also, in case you're wondering what that "xor a" there stands for, it is actually instruction "xor a, a" and stores the result in a. When you xor a value with itself, the value turns into 0 (or here $00 because we have 8-bit registers). https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/xor.html

Basically, that instruction there simply performs "ld a, 00" but takes one byte less. You'll see that often in GB/C code.
In case there is something else that confuses you about the code, feel free to ask. That just popped in my mind that it might not make any sense what that is for and makes the routine feel confusing.

I'm kinda confused on where that's meant to go. D'you mean I should keep the "No point in reducing 1 or 0 damage" bit and replace the rest-- everything afterwards-- with the second code box you wrote? Sorry if it seems I'm verging on what some may call "asking for spoon-fed information," but I'm still fairly new to this sort of thing.

Also, that "xor a" thing should prove useful. Thanks.
 

miksy91

Dark Energy is back in action! ;)
1,480
Posts
15
Years
I'm kinda confused on where that's meant to go. D'you mean I should keep the "No point in reducing 1 or 0 damage" bit and replace the rest-- everything afterwards-- with the second code box you wrote? Sorry if it seems I'm verging on what some may call "asking for spoon-fed information," but I'm still fairly new to this sort of thing.
That is the whole routine I just wrote in my previous post. You should be able to call it directly the way you had intended. But depending on whether at the end of the routine, register pair bc should be loaded with the value in "CurDamage" - "CurDamage + 1" (b = [CurDamage], c = [CurDamage + 1]), you may have to adjust the code a little bit.

That adjusting would practically mean that you had to change that "ret nz" in the middle of the code as "jr nz .return", and put address ".return" following all the code in the end. Notice that in this version, there is instruction "dec hl" at the end just before ".return" so that hl points to CurDamage every time ".return" is executed.

Code:
	ld hl, BattleMonItem
	ld a, [hBattleTurn]
	and a
	jr z, .got_item_addr
	ld hl, EnemyMonItem
.got_item_addr
	ld a, [hl]
	cp STICK
	ld hl, CurDamage
	jr nz .return // hl points to CurDamage when .return is executed

	xor a
	ld [hMultiplicand + 0], a
	ld a, [hli]
	ld [hMultiplicand + 1], a
	ld a, [hl]
	ld [hMultiplicand + 2], a // set [hMultiplicand + 0] - [hMultiplicand + 2] as the originally calculated damage

; Multiply by 85%
	ld a, $d4 ' (= 212)
	ld [hMultiplier], a
	call Multiply // multiply the originally calculated damage by 0xD4

; ...divide by 100%...
	ld a, $ff ; 100%
	ld [hDivisor], a
	ld b, $4
	call Divide // divide the multiplied value by 0xFF

; ...to get 0.83 damage
	ld a, [hQuotient + 1]
	ld hl, CurDamage
	ld [hli], a
	ld a, [hQuotient + 2]
        ld [hl], a // store [(Original damage) * 0,83] into [CurDamage] - [CurDamage + 1]
        dec hl // hl points to CurDamage when .return is executed

.return
	ld b, [hl]
	inc hl
	ld c, [hl] // set bc as the done damage
	ret

If you take a look at the code provided by PikaLaxt:
Code:
ReduceNumberByAPercent: ; thanks PikalaxALT!
	; number in bc, percentage in a
	push af
	ld a, b
	ld [hMultiplicand + 1], a
	ld a, c
	ld [hMultiplicand + 2], a
	xor a
	ld [hMultiplicand], a
	pop bc
	ld a, 100
	sub b
	ld [hMultiplier], a
	call Multiply
	ld a, 100
	ld [hDivisor], a
	ld b, 4
	call Divide
	ld a, [hQuotient + 1]
	ld b, a
	ld a, [hQuotient + 2]
	ld c, a
	ret
You should be able to see that when it returns, b contains the more significant byte of the calculated damage (= higher value) and c the less significant byte. The reason for this is that I believe that function "Divide" stores the value of dividing into [hQuotient + 1] - [hQuotient + 2]. If it didn't it wouldn't make any sense to call that Divide function either since its results wouldn't be used in any way.

Also, that "xor a" thing should prove useful. Thanks.
No prob :)
 
Last edited:
Back
Top