Greatest RPG Fans Forum

"Spell bug - SOLVED"

Printer-friendly version of this topic
Bookmark this topic (Registered users only)
 
Previous Topic | Next Topic 
Conferences Wizardry(r) 1-7 Conferences Wiz 6 - Oh, don't be so Banal ;) (Protected)
Original message

PortableGorilla (11 posts) Click to EMail PortableGorilla Click to send private message to PortableGorilla Click to view user profile Click to check IP address of the poster
May-10-10, 07:33 AM (Pacific)
"Spell bug - SOLVED"
LAST EDITED ON May-17-10 AT 05:53 AM (Pacific)

I may have discovered the source of the spell bug that causes monsters to resist the 7th level “attack all” spells. I’m working on seeing if there is an in-game fix or a way to patch the problem.

Here’s what I’ve got:

When a caster casts a spell on a target, the game rolls a saving throw for the target:
If(1d100-1 <= target_resistance – resistance_adjustment)
{
target resists spell
}
• target_resistance is the resistance % shown in Mad God’s editor
• resistance_adjustment = (caster_level – target_level + caster_bonus)
o caster_level is the caster’s level (or hit dice for monsters)
o target_level is the target’s level (or hit dice for monsters)
o caster_bonus = 3*(spell_level + power_level – 2)
 power_level is the power level selected (1-6)

EDIT: I just discovered Mad God has a new version of his editor up that allows spell editing. What he calls "spell efficiency" is the same as what I called "resistance_adjustment"

The “spell bug” occurs when the game attempts to determine target_level. it tries to do an array lookup, which in c-code is essentially struct battle_participant** BATTLE_PARTICIPANTS{target_group}{target}.
• BATTLE_PARTICIPANTS is an array of pointers located at 1110:43a8
o index 0 is the party,
o index 1 is monster group 1,
o and so on, so that
o BATTLE_PARTICIPANTS{0}{x} corresponds to individual x in the party (x=0 is upper left, x=1 is upper right, etc.)
o BATTLE_PARTICIPANTS{1}{x} corresponds to individual x in monster group 1,
o etc.
• battle_participant is a 0x2C-byte wide struct,
o offset 0x00 of which is the participant’s level or hit dice,
o offset 0x20 of which is the index in BATTLE_PARTICIPANTS of the group that participant is targeting that round, and
o offset 0x1F of which is the index in BATTLE_PARTICIPANTS{target_group} of the individual in target_group that participant is targeting that round

So if the party member in the upper right cast energy blast on monster 3 in monster group 1,
*( ((char*)BATTLE_PARTICIPANTS{0}{1})+0x1F)==1 //corresponding to monster group 1, and
*( ((char*)BATTLE_PARTICIPANTS{0}{1})+0x20)==3 //corresponding to individual monster 3

So for a party member casting a spell, the game attempts to determine the resistance_adjustment by doing the following:

NOTE: battle_participant* caster_ptr = &(battle_participants{0}{x}), where x is the index of the caster (0=upper left, 1=upper right, etc.)

function cast_spell(battle_participiant* caster_ptr, int spell_code, int power_level, …)
{
int target_group=(int) ( caster_ptr->target_group ); //executed as *( ((char*)caster_ptr)+0x1F);
int target=(int) ( caster_ptr->target ); //executed as *( ((char*)caster_ptr)+0x20)

register int caster_bonus=calculate_caster_bonus(int spell_code, int power_level);

resistance_adjustment = *caster_ptr – *(BATTLE_PARTICIPANTS{target_group}{target}) + caster_bonus;
//SHOULD == caster_level – target_level + caster_bonus. But it doesn’t always! See below for why this is.

}

The problem is that for character x casting an “attack all” spell, the game sets BATTLE_PARTICIPANTS{0}{x}.target_group==(char) (-1) == (int) 255

So, when the game does BATTLE_PARTICIPANTS{target_group}, this takes it to a random point in memory past the end of BATTLE_PARTICIPANTS (it happens to be the 5th-8th hex digits of the upper right character’s experience points). It then casts the result as a pointer and tries to index into it 0x2C*target bytes, which is another random point in memory. If the result is a large positive integer, target_level will be large and positive, and so resistance_adjustment will be large and negative. This makes the monster’s resistance effectively extremely high! While target_group is consistently 0xFF, target is inconsistent. It is usually 0x00, but it is occasionally 0x02.

You can test this easily. Just have the upper-right character change classes so his/her experience is zero. This should fairly consistently work, but not always, since target is sometimes 0x02. (*0x0000 == 0, but *(0x2c*2) is not necessarily == 0).

In fact, you can often avoid the bug if the 5th and 6th hex digits of your experience points are even and less than 0x56 or so (the numbers in *0x0000-*0x0056 seem to always be 0xff or less. So, divide the upper right character’s experience points by 65536 (decimal) and round down. If the result is even and less than 86 (decimal), your spells should usually work.

---

Here are some notes for others who want to verify. All memory addresses are what I got using dosbox to debug, and are only valid in the middle of a battle after you’ve selected “start fighting” and the animations have begun (I’m not sure which overlay this is in).

0138: b3e1 calls 0138: 9405 (the function described above). In this function,
• caster_ptr is at bp+4,
• spell_code is at bp+6,
• power_level is at bp+8,
• target is at bp-8,
• target_group is at bp-6,
• calculate_caster_bonus starts at 0138: 7816 (the return is stored in ax and pushed on the stack),
• resistance_adjustment is at bp-0x0a
Eventually 9405 calls 0138: 861e (call at 0138: 96ad). In 861e, resistance_adjustment is at bp+0x0e.
Eventually 861e calls 0138: 8149 (call at 0138: 864d). In 8149, resistance_adjustment is at bp+0x10.
• NOTE: 8149 is called once for each group targeted by a spell; this is where they should have calculated resistance_adjustment. I haven’t looked to see if there is any code in there that is somehow failing to overwrite the resistance_adjustment incorrectly calculated above
Eventually 8149 calls 0138: 7ddc (call at 0138: 81c2). In 7ddc, resistance_adjustment is at bp+0x10.

In 7ddc, at 0138: 7e66, the game does
If(rnd(0 to 99) <= target_resistance – resistance_adjustment)
{
//target resists spell
}

Additional note about the function calculate_caster_bonus at 0138: 7816:
This function does:
{
register int spell_level=*( ((char*)0xDF) + 6*spell_code)
return 3*(spell_level + spell_power – 2);
}

Where does the 0xFF come from?
When you select “spell” when choosing a command, the game sets 0xFF as a default value for target_group at 0138: 7b86. This is overwritten for spells that have a group or individual target at 0138: 6f9a. However, this is never executed for spells that don’t have a group or individual target as a result of a jump to 0138: 6f9d at 0138: 6f64. Note that 0xFF is the target_group for more than just the “attack all” spells. Fire/ice/air shield, blink, create life/illusion/conjuration, and haste all have target_group==0xFF, and usually target==0x00. Enchanted blade, armorplate, and magic screen have target_group==0xFF, and target==0xFF.

  Alert Edit | Reply | Reply With Quote | Top

  Table of Contents

 
 
Lobby | Topics | Previous Topic | Next Topic

Messages in this topic

PortableGorilla (11 posts) Click to EMail PortableGorilla Click to send private message to PortableGorilla Click to view user profile Click to check IP address of the poster
May-10-10, 08:42 AM (Pacific)
1. "RE: Spell bug - SOLVED"
LAST EDITED ON May-12-10 AT 09:08 PM (Pacific)

<deleted>

  Remove | Alert Edit | Reply | Reply With Quote | Top

mad god (4 posts) Click to EMail mad%20god Click to send private message to mad%20god Click to view user profile Click to check IP address of the poster
May-10-10, 03:09 PM (Pacific)
2. "RE: Spell bug - SOLVED"
Hard to believe, but it really is.
As your level grows, though you overcome resistances more easily.
  Remove | Alert Edit | Reply | Reply With Quote | Top

PortableGorilla (11 posts) Click to EMail PortableGorilla Click to send private message to PortableGorilla Click to view user profile Click to check IP address of the poster
May-11-10, 09:24 PM (Pacific)
3. "RE: Spell bug - SOLVED"
LAST EDITED ON May-11-10 AT 09:35 PM (Pacific)

I've successfully made a patch -- if anybody is interested in it, I can give it to you. Feel free to pass it to anybody else who's interested too. I'm really looking forward to a replay where I can finally use the level 7 spells!

  Remove | Alert Edit | Reply | Reply With Quote | Top

Sir Blue (16 posts) Click to EMail Sir%20Blue Click to send private message to Sir%20Blue Click to view user profile Click to check IP address of the poster
May-15-10, 11:30 PM (Pacific)
4. "RE: Spell bug - SOLVED"
Now that's good news!

Is the patch available for download somewhere?

  Remove | Alert Edit | Reply | Reply With Quote | Top

PortableGorilla (11 posts) Click to EMail PortableGorilla Click to send private message to PortableGorilla Click to view user profile Click to check IP address of the poster
May-16-10, 07:56 AM (Pacific)
5. "RE: Spell bug - SOLVED"
Hi,

I don't have a place to make it available, but Mad God is working on adding it to Cosmic Forge. If you give me an email address I can email you a copy.

  Remove | Alert Edit | Reply | Reply With Quote | Top

Scary (16 posts) Click to EMail Scary Click to send private message to Scary Click to view user profile Click to check IP address of the poster
May-18-10, 01:27 PM (Pacific)
6. "RE: Spell bug - SOLVED"
I'm impressed. I don't begin to grasp all of the references, but I understand the explanation at a high level. Thanks for not only solving it but also coming up with a bug fix.
  Remove | Alert Edit | Reply | Reply With Quote | Top

Snafaru (35 posts) Click to EMail Snafaru Click to send private message to Snafaru Click to view user profile Click to check IP address of the poster
Jul-18-10, 06:39 PM (Pacific)
7. "RE: Spell bug - SOLVED"
Can you send it to me at snafaru at zimlab dot com and I'll put it up.

Thanks,

Snafaru
http://www.zimlab.com/wizardry

  Remove | Alert Edit | Reply | Reply With Quote | Top

Snafaru (35 posts) Click to EMail Snafaru Click to send private message to Snafaru Click to view user profile Click to check IP address of the poster
Aug-04-10, 08:33 PM (Pacific)
8. "RE: Spell bug - SOLVED"
Hi PortableGorilla and everyone,

I've put the patch on my web site at: http://www.zimlab.com/wizardry/ in the Wizardry 6 section towards the end of the page.

I've also advertized the patch at http://vnboards.ign.com/board.asp?brd=5140

Snafar

  Remove | Alert Edit | Reply | Reply With Quote | Top

supersonic (4 posts) Click to EMail supersonic Click to send private message to supersonic Click to view user profile Click to check IP address of the poster
May-01-11, 11:05 AM (Pacific)
9. "RE: Spell bug - SOLVED"
Many thanks for posting the patch. It works perfectly for the spells that cause damage, but unfortunately not for the 'instant' death spells (asphyxiation and death wish).
  Remove | Alert Edit | Reply | Reply With Quote | Top

PortableGorilla (11 posts) Click to EMail PortableGorilla Click to send private message to PortableGorilla Click to view user profile Click to check IP address of the poster
May-01-11, 06:35 PM (Pacific)
10. "RE: Spell bug - SOLVED"
It should work fine for both! Who are you trying it against and at what spell level? The 'instant' death spells aren't supposed to always work --

1) many monsters are resistant, especially to asphyxiation.

2) whether they work depends on several factors, especially the spell level.

have a high level character try a level 6 'instant' death spell against rats, and it should work every time. (but in my experience, a level 6 death wish should work a high % of the time against just about anything)

  Remove | Alert Edit | Reply | Reply With Quote | Top

supersonic (4 posts) Click to EMail supersonic Click to send private message to supersonic Click to view user profile Click to check IP address of the poster
May-26-11, 01:10 PM (Pacific)
11. "RE: Spell bug - SOLVED"
Seems to work now! It failed against a group of Guardians of Ramm on full power (asphyxiation) with a level 20 charachter. I thought I remember it working against these when on the Amiga.

Many thanks.

  Remove | Alert Edit | Reply | Reply With Quote | Top

woosea (1 posts) Click to EMail woosea Click to send private message to woosea Click to view user profile Click to check IP address of the poster
May-31-17, 06:02 PM (Pacific)
12. "RE: Spell bug - SOLVED"
Congratulations and many thanks for your fine work!
By the way , I'm playing wiz6 "steam"version on my mac book.
Would you know How can I get the patch in this case ?
  Remove | Alert Edit | Reply | Reply With Quote | Top

Geryth (20 posts) Click to EMail Geryth Click to send private message to Geryth Click to view user profile Click to check IP address of the poster
Jul-12-17, 09:51 PM (Pacific)
13. "RE: Spell bug - SOLVED"
I suggest downloading Mad God's Cosmic Forge editor. It has a "patches" menu that should include fixes for things like this.

http://mad-god.webs.com/cosmicforge.htm

  Remove | Alert Edit | Reply | Reply With Quote | Top


Lock | Archive | Remove

Lobby | Topics | Previous Topic | Next Topic
Rate this topic (1=skip it, 10=must read)? [ 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 ]
Powered by DCF2000 ©1997-2000 by DCScripts. All rights reserved.