Items and Monsters for Wizardry IV

This commit is contained in:
Denis Molony 2022-05-28 12:59:25 +10:00
parent 0b72f1a37d
commit c4b4d17f52
10 changed files with 159 additions and 43 deletions

View File

@ -3,7 +3,7 @@ package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
class CodedMessage extends Message
class CodedMessage extends MessageV1
// -----------------------------------------------------------------------------------//
{
public static int codeOffset = 185;

View File

@ -0,0 +1,16 @@
package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile;
// -----------------------------------------------------------------------------------//
public class ItemV4 extends AbstractFile
// -----------------------------------------------------------------------------------//
{
// ---------------------------------------------------------------------------------//
ItemV4 (String[] names, byte[] buffer, int id)
// ---------------------------------------------------------------------------------//
{
super (names[1], buffer);
}
}

View File

@ -49,7 +49,7 @@ class MazeCell
MazeAddress address;
MazeAddress addressTo; // if teleport/stairs/chute
public Message message;
public MessageV1 message;
public List<Monster> monsters;
public Item itemRequired;
public Item itemObtained;

View File

@ -24,7 +24,7 @@ public class MazeLevel extends AbstractFile
"Rock/Water", "Fizzle", "Message/Item", "Monster" };
public final int level;
private List<Message> messages;
private List<MessageV1> messages;
private List<Monster> monsters;
private List<Item> items;
@ -94,7 +94,7 @@ public class MazeLevel extends AbstractFile
text.append ("\n\n");
for (MazeAddress address : messageList)
{
Message message = getMessage (address.row);
MessageV1 message = getMessage (address.row);
if (message != null)
{
text.append (String.format ("%nMessage: %04X (%d)%n", address.row, address.row));
@ -318,7 +318,7 @@ public class MazeLevel extends AbstractFile
}
// ---------------------------------------------------------------------------------//
public void setMessages (List<Message> messages)
public void setMessages (List<MessageV1> messages)
// ---------------------------------------------------------------------------------//
{
this.messages = messages;
@ -448,7 +448,7 @@ public class MazeLevel extends AbstractFile
case 11: // screen message
MazeAddress messageAddress = getAddress (b);
Message m = getMessage (messageAddress.row);
MessageV1 m = getMessage (messageAddress.row);
if (m != null)
cell.message = m;
@ -513,13 +513,13 @@ public class MazeLevel extends AbstractFile
}
// ---------------------------------------------------------------------------------//
private Message getMessage (int messageNo)
private MessageV1 getMessage (int messageNo)
// ---------------------------------------------------------------------------------//
{
if (messages == null)
return null;
for (Message m : messages)
for (MessageV1 m : messages)
if (m.match (messageNo))
return m;

View File

@ -33,14 +33,27 @@ class MessageBlock extends AbstractFile implements Iterable<MessageDataBlock>
int firstMessageNo = Utility.getShort (buffer, ptr + i * 2);
byte[] data = new byte[512];
System.arraycopy (buffer, i * 512, data, 0, data.length);
MessageDataBlock messageDataBlock = new MessageDataBlock (
" Message " + firstMessageNo, data, firstMessageNo, huffman);
MessageDataBlock messageDataBlock =
new MessageDataBlock (" Message " + firstMessageNo, data, firstMessageNo, huffman);
messageDataBlocks.add (messageDataBlock);
}
}
// ---------------------------------------------------------------------------------//
public String getMessageText (int messageNo)
public byte[] getMessage (int messageNo)
// ---------------------------------------------------------------------------------//
{
for (int i = 0; i < messageDataBlocks.size (); i++)
{
MessageDataBlock messageDataBlock = messageDataBlocks.get (i);
if (messageDataBlock.firstMessageNo > messageNo)
return messageDataBlocks.get (i - 1).getMessage (messageNo);
}
return null;
}
// ---------------------------------------------------------------------------------//
public String getMessageLine (int messageNo)
// ---------------------------------------------------------------------------------//
{
for (int i = 0; i < messageDataBlocks.size (); i++)
@ -80,38 +93,25 @@ class MessageBlock extends AbstractFile implements Iterable<MessageDataBlock>
return lines;
}
// ---------------------------------------------------------------------------------//
public byte[] getMessage (int messageNo)
// ---------------------------------------------------------------------------------//
{
for (int i = 0; i < messageDataBlocks.size (); i++)
{
MessageDataBlock messageDataBlock = messageDataBlocks.get (i);
if (messageDataBlock.firstMessageNo > messageNo)
return messageDataBlocks.get (i - 1).getMessage (messageNo);
}
return null;
}
// ---------------------------------------------------------------------------------//
@Override
public String getText ()
// ---------------------------------------------------------------------------------//
{
if (text != null)
return text;
StringBuilder text = new StringBuilder ();
for (MessageDataBlock mdb : messageDataBlocks)
if (text == null)
{
text.append (mdb);
text.append ("\n");
StringBuilder sb = new StringBuilder ();
for (MessageDataBlock mdb : messageDataBlocks)
{
sb.append (mdb);
sb.append ("\n");
}
text = sb.toString ();
}
this.text = text.toString ();
return this.text;
return text;
}
// ---------------------------------------------------------------------------------//

View File

@ -6,7 +6,7 @@ import java.util.List;
import com.bytezone.diskbrowser.applefile.AbstractFile;
// -----------------------------------------------------------------------------------//
abstract class Message extends AbstractFile
abstract class MessageV1 extends AbstractFile
// -----------------------------------------------------------------------------------//
{
private static int nextId = 0;
@ -16,7 +16,7 @@ abstract class Message extends AbstractFile
List<String> lines = new ArrayList<> ();
// ---------------------------------------------------------------------------------//
Message (byte[] buffer)
MessageV1 (byte[] buffer)
// ---------------------------------------------------------------------------------//
{
super ("Message " + nextId, buffer);

View File

@ -0,0 +1,14 @@
package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.applefile.AbstractFile;
public class MonsterV4 extends AbstractFile
{
// ---------------------------------------------------------------------------------//
MonsterV4 (String[] names, byte[] buffer, int id)
// ---------------------------------------------------------------------------------//
{
super (names[2], buffer);
}
}

View File

@ -3,7 +3,7 @@ package com.bytezone.diskbrowser.wizardry;
import com.bytezone.diskbrowser.utilities.HexFormatter;
// -----------------------------------------------------------------------------------//
class PlainMessage extends Message
class PlainMessage extends MessageV1
// -----------------------------------------------------------------------------------//
{
// ---------------------------------------------------------------------------------//

View File

@ -95,6 +95,8 @@ public class Wizardry4BootDisk extends PascalDisk
scenarioHeader = new Header (scenarioNode, this);
linkCharacters4 (scenarioNode, fileEntry);
linkMazeLevels4 (scenarioNode, fileEntry);
linkMonstersV4 (scenarioNode, fileEntry);
linkItemsV4 (scenarioNode, fileEntry);
}
}
else if (version == 5)
@ -173,6 +175,90 @@ public class Wizardry4BootDisk extends PascalDisk
afs.setSectors (allCharacterBlocks);
}
// ---------------------------------------------------------------------------------//
private void linkMonstersV4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{
ScenarioData sd = scenarioHeader.get (Header.MONSTER_AREA);
byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors ();
DefaultMutableTreeNode monstersNode = linkNode ("Monsters", "Monsters", scenarioNode);
List<DiskAddress> allMonsterBlocks = new ArrayList<> ();
String[] monsterNames = new String[4];
int ptr = sd.dataOffset * 512;
for (int i = 0; i < sd.total; i++)
{
byte[] out = huffman.decodeMessage (buffer, ptr, sd.totalBlocks);
for (int j = 0; j < 4; j++)
monsterNames[j] = messageBlock.getMessageLine (i * 4 + 13000 + j);
MonsterV4 monster = new MonsterV4 (monsterNames, out, i);
List<DiskAddress> monsterBlocks = new ArrayList<> ();
DiskAddress da = blocks.get (ptr / 512);
monsterBlocks.add (da);
addToNode (monster, monstersNode, monsterBlocks);
if (!allMonsterBlocks.contains (da))
allMonsterBlocks.add (da);
ptr += sd.totalBlocks;
}
DefaultAppleFileSource afs = (DefaultAppleFileSource) monstersNode.getUserObject ();
afs.setSectors (allMonsterBlocks);
}
// ---------------------------------------------------------------------------------//
private void linkItemsV4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
{
ScenarioData sd = scenarioHeader.get (Header.ITEM_AREA);
byte[] buffer = fileEntry.getDataSource ().buffer;
List<DiskAddress> blocks = fileEntry.getSectors ();
DefaultMutableTreeNode itemsNode = linkNode ("Items", "Items", scenarioNode);
List<DiskAddress> allItemBlocks = new ArrayList<> ();
String[] itemNames = new String[2];
int ptr = sd.dataOffset * 512;
for (int i = 0; i < sd.total; i++)
{
byte[] out = huffman.decodeMessage (buffer, ptr, sd.totalBlocks);
for (int j = 0; j < 2; j++)
{
itemNames[j] = messageBlock.getMessageLine (i * 2 + 14000 + j);
if (itemNames[j] == null)
itemNames[j] = "Not found";
}
ItemV4 item = new ItemV4 (itemNames, out, i);
List<DiskAddress> itemBlocks = new ArrayList<> ();
DiskAddress da = blocks.get (ptr / 512);
itemBlocks.add (da);
addToNode (item, itemsNode, itemBlocks);
if (!allItemBlocks.contains (da))
allItemBlocks.add (da);
ptr += sd.totalBlocks;
}
DefaultAppleFileSource afs = (DefaultAppleFileSource) itemsNode.getUserObject ();
afs.setSectors (allItemBlocks);
}
// ---------------------------------------------------------------------------------//
private void linkMazeLevels4 (DefaultMutableTreeNode scenarioNode, FileEntry fileEntry)
// ---------------------------------------------------------------------------------//
@ -343,11 +429,11 @@ public class Wizardry4BootDisk extends PascalDisk
int key = Utility.getShort (buffer, offset);
if (key > 0)
text.append (
String.format ("%04X %04X * %s%n", offset, key, messageBlock.getMessageText (key)));
String.format ("%04X %04X * %s%n", offset, key, messageBlock.getMessageLine (key)));
key = Utility.getShort (buffer, offset + 8);
if (key > 0)
text.append (String.format ("%04X %04X %s%n", offset + 8, key,
messageBlock.getMessageText (key)));
messageBlock.getMessageLine (key)));
}
List<DiskAddress> allOracleBlocks = new ArrayList<> ();

View File

@ -33,7 +33,7 @@ public class WizardryScenarioDisk extends PascalDisk
public List<Item> items;
public List<Character> characters;
public List<Spell> spells;
public List<Message> messages;
public List<MessageV1> messages;
public List<Monster> monsters;
public List<MazeLevel> levels;
List<ExperienceLevel> experiences;
@ -448,7 +448,7 @@ public class WizardryScenarioDisk extends PascalDisk
private void extractMessages (DefaultMutableTreeNode node, List<DiskAddress> sectors)
// ---------------------------------------------------------------------------------//
{
Message.resetMessageId ();
MessageV1.resetMessageId ();
messages = new ArrayList<> ();
// Copy first 504 bytes from each sector to a single contiguous buffer
@ -479,7 +479,7 @@ public class WizardryScenarioDisk extends PascalDisk
int messageStart = messageEnd - totalBytes;
System.arraycopy (buffer, messageStart, newBuffer, 0, totalBytes);
Message m;
MessageV1 m;
if (scenarioHeader.scenarioID == 1)
m = new PlainMessage (newBuffer);
else