Wednesday, December 19, 2007

Diablo II: Martial Arts Assassin Skill Layout

A martial arts assassin is a melee fighter who relies mostly on charge up skills and kicks to deal damage to their enemies. Along with these they have several utility skills that provide excellent crowd control of monster packs. The skill setup is as follows:

Tiger Strike - 1
Claw Mastery - 1
Dragon Talon - 1
Psychic Hammer - 1
Burst of Speed - 1

At level six Burst of Speed becomes available, which enables the assassin to move and attack at extremely fast speeds. This skill will be the key to this build, as it will allow charge-ups to be obtained in rapid succession and therefore damage dealt to monster packs released with minimal time in between. Only one hard point here is needed as plus skills from equipment will handle the rest of the needed leveling.

Fists of Fire - 1
Dragon Claw - 1
Tiger Strike - 3
Cobra Strike - 1
Weapon Block - 1
Cloak of Shadows - 1

At level twelve to major skills become available; Cobra Strike and Cloak of Shadows. Cobra Strike allows the character to leech mana and life from monsters at extremely high rates, keeping the bulbs full at all times. Cloak of Shadows is the assassin's main crowd control skill, and should be utilized whenever a pack of monsters is encountered. Only one point is desired in both of these skills, as plus skills from equipment will handle the rest of the leveling needs.

Tiger Strike - 5
Claws of Thunder - 1
Dragon Tail - 1
Fade - 1
Shadow Warrior - 1

At level eighteen Shadow Warrior becomes available, which makes an excellent tank. This will allow the character to attack monsters at the edge of the pack for charge-up purposes before unleashing damage into the heart of the monster's formation.

Tiger Strike - 10
Blades of Ice - 1
Dragon Flight - 1

Dragon Flight is used in special circumstances only to teleport the assassin across the field. Extremely handy to escape from trapped positions and provide some breather room to regroup.

Tiger Strike - 14
Phoenix Strike - 1
Shadow Master - 1

At level thirty the ultimate tank becomes available, Shadow Master. The Shadow Master has the ability to cast their own Crowd Control spells, such as Mind Blast and Cloak of Shadows, which makes survivability for the main character exponentially easier. There is also the down side however, Mind Blast will be cast on a monster the main character is attack fairly often and this can lead to some confusing battles.

Tiger Strike - 20
Phoenix Strike - 20
Dragon Tail - 20

At level sixty-eight all of the main skills are maximized and now a decision must be made, which synergy to Phoenix Strike to dump the remaining points into. Since Dragon Tail provides extra fire damage then Fists of Fire is not really a consideration. Either of the two remaining options (cold/lightning) are viable and helpful, however the decision for me was quite easy. I found it extremely difficult to see how many glowing charge-up balls were floating around the character. Either monsters, barrels, trees or spell effects blocked the view of these charge-up indicators, so whenever they were released it was virtually impossible to tell what element was going to be given. Since lightning is the second of three charge-ups it is harder to force this skill to be released as cold, which is the last charge-up. As a result I suggest Blades of Ice as the synergy to increase.

Blades of Ice - 20

At level eighty-three the character is complete. Not many pieces of equipment are requirements for this character, however items with plus skills are extremely helpful due to the scaling factor of the martial arts skills and the need to increase some of the utility skills that receive only one hard skill point. Along with this a high damage set of boots is needed to provide the bulk of the damage from Tiger Strike and Dragon Tail. Goreriders or Shadow Dancers are the best choices for this.

Sunday, December 16, 2007

Diablo II: Matriarch Nemesis

Nemesis is a recreation of a martial arts assassin I had started both on Battle.net and Single Player but never finished. On Bnet I quit and moved to SP, and on SP I restarted before I finished. As a result I've never even gotten an assassin into Hell, such an oversight had to be corrected.

As can be expected Normal was a bit difficulty to begin with, but once Tiger Strike was maximized the questing was fairly basic. Tactics weren't really required yet, even untwinkled. I did however have great difficulty once more skills became available. Up to this point I've always utilized the F* keys for my skills as normally I use no more than six skills overall. However for an assassin this simply wasn't possible. As a result I had to bind the A-S-D-F-Q-W-E-R-T keys, as I was finding myself getting more and more frustrated by the fact I couldn't select the needed skills quickly enough. Obviously this lead to some confusion for a while right after the switch trying to use potions, as my hand was in a different location. I can attribute a few Normal deaths to this issue.

Nightmare on the other hand, wasn't quite as easy as expected. A trip into the Blood Moor lead to a triple boss pack that killed off my poor barbarian mercenary and shadow master almost instantly and required lots of running around and trips back to town for potion restocks before they were eliminated. The mods weren't very dangerous, it was the cold damage the undead inflicted that was the problem. Being slowed simply didn't mesh with how Nemesis was intended to be played. So I muled on a pair of 20% faster attack speed gloves and a Ravenfrost ring to correct that issue.

Afterwards progress was fairly good. Charge-ups were used everywhere, no more normal attacks. The most dangerous monsters were either manaburn or undead, due to the inability to leech from them. Up until Act IV the normal packs were manageable, as were the act bosses. Duriel required some thawing potions as Nemesis still has zero, well now -30%, cold resistance. Duriel was also the only act boss to require a trip back to town to restock on health potions, both Andariel and Mephisto were easily dealt with due to the ability to leech from them.

Act IV lead to more problems due to the ramped up health/damage of the monster packs. Just stepping out of the staircase lead to a doom knight boss pack (extra fast, cursed) that killed Nemesis at least five times. They were accompanied by a few pit lords that took three sets of charge-up and release cycles to kill a single one. The weapon/boots Nemesis had were simply
lacking enough punch to deal with the monsters. So a few more items needed to be muled on; Gore Riders and a Bartuc's Cut-Throat. Afterwards Nemesis was able to deal with the monster packs, it still wasn't a breeze but manageable.

At arriving at the Chaos Sanctuary she realized something, Cloak of Shadows apparently doesn't affect Oblivion Knights, as they kept cursing her. This lead to several deaths to IM before the player settings were dropped to one for the rest of the level. The same held true in the WSK against the Oblivion knights that spawned there as well. Lovely. Ended up with a nasty roll for the 3rd level, Revivers coupled with a level simply full of Gloams. It was just plain silly, but being stubborn I refused to reroll the map, and died several times as a result.

Finally Hell was reached, which means Nemesis can be twinkled up to her eyebrows, and she was: helm, armor, rings, amulet, belt and a second weapon to join the twinkled main weapon, boots and gloves already present. After that she simply ran, literally, through Hell. With all of the bonus skill points given by equipment Nemesis had Burst of Speed up to a very respectable level, too much actually. Took quite a bit of getting used to how fast she could move.

One thing that did cause problems is the fact that more often than not I could not see how many light balls were circling her feet. This became a problem when using Phoenix Strike, I had no idea which elemental attack was going to be released. This lead to many of them being wasted due to being directed on immune monsters, but also to 17 skill points being unused at the end of the game. Since I couldn't control which element to release I didn't want to use the points in synergies when a need may arise for them later. No need arose however so I think I'll dump them all into Blades of Ice, since the last charge is a little easier to control even if Claws of Thunder was my first choice when planning the character.

Nemesis didn't encounter any terrible problems until the Chaos Sanctuary in Act IV, due to the Oblivion Knights and IM. Since Cloak of Shadows doesn't affect OKs she struggled greatly in this area and received her first death in Hell, then several more followed close behind. This was a signal for things to come in Act V, as in the Bloody Foothills Nemesis and her companions were greeted with hordes of ranged monsters. Cloak of Shadows was used liberally to allow Nemesis to clear out small packs at a time. Going was slow but steady until the Ancients.

The Ancients had a dangerous set of mods. Talic (Whirlwind) was extra fast and spectral hit enhanced while Korlic was extra fast and stone skin. Of course both of them zeroed in on Nemesis and completely ignored her companions. This resulted in several minutes of her running around (with BoS enabled) with both hot on her heels. Since they were just as fast splitting up the Ancients simply wasn't possible, so hit and fade tactics had to be used to eliminate Madawc first and then corner Talic and Korlic behind a pillar where they couldn't see Nemesis. At this point they engaged Alhizeer and the Shadow Master, mostly the Shadow Master. This was good as Nemesis had run out of purple and red potions by this point.

Eventually they fell, then the WSK gave an extremely challenging combination of monsters to test Nemesis' skill and courage. Level 1 was easy, level 2 had Souls and Snakes, level 3 had Oblivion Knights and level 4 was fulled with Souls, Hell Witches and Death Lords. The last level was virtually unfair, fighting cursed with Amplify damage constantly against multiple bosspacks and champion packs of Death Lords, who in my opinion are the most dangerous melee monsters in the game.

Needless to say many mercenary resurrections were required, but eventually Baal was engaged and defeated, even though he felt his clone needed to remain a constant companion. Nemesis used a little trick to deal her damage; she charged up on the festering appendages that Baal kept summoning then released their charges on Baal himself. Since she had issues hitting Baal this was the only way to drop the Lord of Destruction.

Stats:
Level 81
Strength - 94(161)
Dexterity - 86(116)
Vitality - 295(305)
Energy - 25(35)

Life - 1095(1267)
Mana - 145(184)

Lightning Resistance - 75
Fire Resistance - 75
Cold Resistance - 75
Poison Resistance - 75

Skills:
Tiger Strike - 20(29)
Phoenix Strike - 20(29)
Dragon Tail - 20(29)
Dragon Flight - 1(10)
Fade - 1(7)
Shadow Master - 1(7)

Equipment:
Weapon 1: Bartuc's Cut-Throat (Shael)
Weapon 2: Jade Talon (24% CR jewel)
Armor: Duriel's Shell
Boots: Gore Rider
Belt: +15 Strength, FR 25%, LR 25%, 24% FHR, PLR 25%
Gloves: PR 25%, 20% IAS, +2 Martial Art skills
Helm: +18 Resist All, 6% Mana steal, +2 Assassin skills
Ring 1: +7 Strength, +22 Mana, LR 28%
Ring 2: Nature's Peace
Amulet: The Mahim-Oak Curio

Mercenary (Holy Freeze Desert Warrior):
Helm: Tal Rasha's Crest
Armor: Shaftstop
Weapon: The Reaper's Toll

Hellforge
NM: Um
Hell: Hel

Thursday, December 6, 2007

Diablo II: Pindlethon IV

A Pindlethon is an event run about once per year in the SPF. The basic idea is that each participant kills Pindleskin two thousand times during the month long event. Each elite unique and set item is considered a qualifier and those numbers are tracked. The participant with the best 5 items wins. Normally the top few players get to take an item or two from those below them, but that was left out of this Pindlethon. That was something I don't mind too much since I found several grailers that I didn't want to lose, and since I'm self found if my some miracle I won I wouldn't be taking items from anyone.

Here's the loot I collected during my runs.

#5
Spirit Ward
Ward
Defense: 446
Chance to Block: 69%
Smite Damage: 11 to 35
Durability: 67 of 100
Required Strength: 185
Required Level: 68
Item Version: 1.10 Expansion
Item Level: 86
Fingerprint: 0xafc33759
+161% Enhanced Defense
+25% Increased Chance of Blocking
All Resistances +37
25% Faster Block Rate
+6 Cold Absorb
5% Chance to cast Level 8 Fade when struck

#4
M'avina's True Sight
Diadem
Defense: 210
Durability: 10 of 20
Required Level: 64
Item Version: 1.10 Expansion
Item Level: 86
Fingerprint: 0x67d2e9e6
+25 to Mana
+150 Defense
Replenish Life +10
30% Increased Attack Speed

#3
M'avina's True Sight
Diadem
Defense: 207
Durability: 19 of 20
Required Level: 64
Item Version: 1.10 Expansion
Item Level: 86
Fingerprint: 0x58423fc5
+25 to Mana
+150 Defense
Replenish Life +10
30% Increased Attack Speed

#2
Griswold's Valor
Corona
Defense: 270
Durability: 37 of 50
Required Strength: 104
Required Level: 69
Item Version: 1.10 Expansion
Item Level: 86
Fingerprint: 0x31e1bfa3
+63% Enhanced Defense
All Resistances +5
26% Better Chance of Getting Magic Items
Requirements -40%
+0 to Cold Absorb (Based on Character Level)

#1
The Cranium Basher
Thunder Maul
Two-Hand Damage: 130 to 624
Required Strength: 253
Required Level: 87
Mace Class - Normal Attack Speed
Indestructible
Item Version: 1.10 Expansion
Item Level: 86
Fingerprint: 0x2062bd2d
+25 to Strength
+236% Enhanced Damage
+20 to Minimum Damage
+20 to Maximum Damage
All Resistances +25
20% Increased Attack Speed
150% Damage to Undead
75% Chance of Crushing Blow
Indestructible
4% Chance to cast Level 1 Amplify Damage on striking

The rest of the finds:

Bloodmoon x2
Bonehew
Boneshade
Cranebeak
Demon Limb x2
Eschuta's Temper
Ethereal Edge
Gimmershred
Hellslayer
IK Stone Crusher
Lightsabre
M'avina's Embrace
Naj's Puzzler
Ondal's Almighty
Ormus' Robes
Rainbow Facet (3/3 lightning)
Trang-Oul's Guise
Wraith Flight

Best runes: Amn - Shael - Hel

It was a fairly bad showing on my part, as I didn't receive a single vote. A lot of that had to do with the fact I ended up with the second least amount of items of anyone who completed their run set. Runs took about forty-five seconds apiece, which is a bit long for such runs but I like to pick up many rare items looking for endgame gear so lots of extra time is taken identifying and selling items. However I did find several items I've never seen before, most notably M'avina's True Sight which gets me one item closer to finishing the set as well as providing solid equipment for my planned bowazons.

Wednesday, December 5, 2007

Java: DII Character Simulator Update #4

The rest of the groundwork for the application was completed with the addition of listeners to each and every JButton, JComboBox and JCheckBox. The equipment tabs were fairly simply due to how similar they are, the code was written for one and then copied to each other class file with only minor adjustments required. These listeners don't do anything yet as the methods that govern the program aren't written, but that is all that is required code-wise for this section.

As for the final stats tab, more than just listeners were added. Along with finishing up any needed listeners the entire page was reworked, specifically the skill display panel was removed. I decided that it was going to be a duplication of work as that same information would be available in the skill calculator tab, so doing it twice was unnecessary. Also, the layout of the final stats panel was a bit crowded, and this freed up the needed space.

Some functionality was added to the buttons and fields of this tab as well. Specifically:

Stat Points panel
  • Plus button has check to ensure points can't be added if no points available
  • Minus button has check to ensure points can't be removed if the base value is displayed
  • Points to Vitality increase the displayed life value
  • Points to Energy increase the displayed mana value

Button panel
  • Character name changed depending on which character type selected in the skills tab
  • Change in Difficulty Finished JComboBox increases the stat points remaining and resistance values
  • Change in character level JComboBox changes remaining stat point value as well as mana/life values

Mods of Note panel
  • The Blocking field was moved to this panel from the Damage/AR panel

Damage/AR panel
  • Blocking was removed
  • Attack rating and Damage fields for Undead and Demon were added

In order to track changes to mods, life, mana and resistances a trio of arrays were created that would hold any additions to these values.

static int[] resistance = {0, 0, 0, 0};
static int[] stats = {0, 0, 0, 0, 0, 0};
static int[] modsOfNote = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

These arrays will be present in each equipment class as well as the final stat class. When an action is taken that could possibly add to any of these values, whether it be adding a vitality point to a piece of equipment, the values of these arrays are summed and the result displayed in the appropriate JTextField.

The only fields that aren't attached to any methods or listeners at this time are the Damage/AR and Misc Mods panels. I'm going to wait until the rest of the program is in place before getting these panels working. This means the next step is to finish the Skill Calculator tab by locating the necessary equations for calculating the skill values and implement a way to view skill bonuses in that tab.

Tuesday, November 27, 2007

Diablo II: Necromancer Summoner Skill Layout

Also known as the Fishymancer, a Necromancer that uses summons to fight is a typical build in Diablo II. There are many variations of such builds; relying on just skeletons, golems or revives. Personally I want as many meat shields as possible for the character, so a combination of all three is used. The skill setup is as follows.

Raise Skeleton - 20
Skeleton Mastery - 20
Raise Skeletal Mage - 20
Corpse Explosion - 20
Summon Resist - 1
Decrepify - 1
Revive - 1
Attract - 1

As well as a single point in all of the prerequisites. I like to provide a breakdown of when each skill point is allocated.

Raise Skeleton - 2
Amplify Damage - 1
Skeleton Mastery - 1
Clay Golem - 1

At level 6 the character will have three skeleton warriors (1 due to starting wand) and a clay golem to deal the necessary damage. This isn't enough to progress quickly, so the character will be engaging in melee combat for the beginning portion of Act I. Monsters are first cursed with Amplify Damage and then engaged in combat.

Raise Skeleton - 7
Golem Mastery - 1
Raise Skeletal Mage - 1

At level twelve the character has four skeleton warriors, one clay golem and a skeleton mage for company, along with the mercenary. The character will still need to engage in melee combat, but the burden of engaging mobs is no longer present.

Raise Skeleton - 9
Skeleton Mastery - 5

At level 18 the character is ready to take on Andariel, with an additional skeleton warrior. The points in Skeleton Mastery will make the summons strong enough to withstand a few hits by Andariel so they don't crumble instantly. Luckily there are always several carver packs right near her, so resummoning any defeated minions is simple.

Raise Skeleton - 12
Weaken - 1
Terror - 1
Summon Resist - 1
Decrepify - 1

At level 24 Decrepify becomes available, which will be used against all act bosses from here to the end of questing. Decrepify, along with a clay golem, will slow the boss down to such a point where they are dealing very little damage to the summons. An extra skeleton warrior is also obtained, giving a total of 9 companions for the character. At this point the character doesn't need to engage in melee combat and can instead sit back cursing monsters and picking up items while the summons do the dirty work. Duriel should be extremely easy to overcome.

Raise Skeleton - 20
Skeletal Mastery - 20

The next objective is to maximize Raise Skeleton to have as many minions as possible. To that end equipment with +summon skills mods are highly sought after. Shopping for wands is advised, as is using the imbune quest reward from Act I on a necromancer head (shield). By the end of the first difficulty level the character has reached level 45 and has at least nine skeleton warriors, one skeletal mage, one clay golem and a mercenary at their disposal.

Bone Armor - 1
Blood Golem - 1
Iron Golem - 1
Revive - 1
Dim Vision - 1
Confuse - 1
Attract - 1
Teeth - 1
Corpse Explosion - 1

Up to level 52 the utility skills are obtained, each will only receive a single point overall and allow plus skill mods on equipment to provide any additional bonuses, except Corpse Explosion of course. However Corpse Explosion will not receive any additional points quite yet. Normally Normal and Nightmare are run at 'players 8', so CE has limited effectiveness due to it's damage not scaling accordingly. Therefore it will only be used as a body disposal skill for reviving monsters.

Raise Skeletal Mage - 20

Next comes mages as minions. They are not anywhere as useful as skeleton warriors due to their lower Hit Points and damage output. However the character can have as many of them as warriors and they can easily act as extra meat shields to keep the monsters off of the player character. Along the way it is suggested (if RWM) to obtain an Insight polearm for the mercenary (Act II Might, NM). Revives are going to be used and they are very mana intensive and require constant recasting, so to avoid stockpiling mana potions the Insight will solve all mana issues immediately. It's only a suggestion however, Insight is not critical to the character's success, but it does make managing 10+ revives much easier.

Corpse Explosion - 20

At level 69 all summon skills are finished and work can now begin on Corpse Explosion, which should take until level 83 to maximize. It is assumed that in Hell the player will lower the settings to 'player 1 or 3', which will make CE an extremely effective mob killer and speed up the character's progress exponentially. Normally when entering Hell the character will have the ability to summon 11-12 warriors/mages, a clay golem and 8-10 revives, along with the always present mercenary. The player character shouldn't be injured very often. The monsters to watch out for are Black Souls (piercing lightning attack) and Slingers (piercing physical attack). Also reviving monsters should have their corpses exploded, otherwise it is very likely monsters will be revived behind the lines right next to the character.

No pieces of equipment are vital to the success of this character. A general rule is that +skill pieces are more desired over resistance providing equipment. With the amount of friendly minions in the game, any elemental attacks will be absorbed by them long before they reach the player character (except Black Soul lightning of course).

Monday, November 26, 2007

Diablo II: No Vitality Tournament

The concept of the No Vitality tournament is simple, no stat points are allowed to be placed in vitality at all. This is the only restriction. Equipment and charms that add to life or vitality are fine to be used at any time. For obvious reasons equipment with +life/vitality mods are highly sought after.

Regardless of which character is chosen life will be an issue, so I decided on a non-melee character to ensure a decent showing in the tournament. The character would be the same as my All Alone character, a summoning Necromancer. That character wasn't anywhere near as boring as I thought it would be, so I wanted to try again and see how far I could go. I expected this character to be a bit easier due to the mercenary being available to get the army started. The main problem was going to be balancing +life and resistance equipment to ensure survivability. I think I did fairly well in that regard.

As it turned out this Fishymancer, named Bob, became my very first Guardian. I won't go into depth on what happened while questing, I did that quite fine in my Guardian thread in the SPF.

I don't play Hardcore outside of the SPF tournaments, so I'm not sure what to do with Bob. Most likely he'll just sit there as a reminder that I can actually solve the game without dying eight thousand times. Some incentive to play smarter is always nice.

Wednesday, November 21, 2007

Java: DII Character Simulator Update #3

I started to attach JTextFields, JComboBoxes and so forth between the different tabbedpanels. While doing so it started to get quite confusing as to what variables needed to be modified when a component's value changed. There was quite a bit of references between tabbedpanels and at this point I had to stop. I had plans of separating the Skills panel into seven separate panels, one for each character type. Since I was starting to reference variables from the Skills panel for the Stats panel, that separation had to be done before anything else.

This was not simple by any means. Each character received a variable in the Skills panel that is called when the corresponding value is chosen in the JComboBox for character selection. Originally I wanted to simply have these character panels extend JPanel and create a panel that is automatically added to the main program. As it turned out, an easier way was to pass a panel from Skills to the character sub-panel and allow that panel to be the framework for the character skill display.

After that is was simply a matter of copying the first character panel into 6 more copies and changing a few variable names. Along with this the Save button that was initially used to populate the characterField JTextField in the Stats panel was removed. The logic behind the button was Incorporated into the character panels. This lead to a new problem, a NullPointerException error occurs when the program is launched. NullPointerException occurs for one of a few reasons:
  • Calling the instance method of a null object
  • Accessing or modifying the field of a null object
  • Taking the length of null as if it were an array
  • Accessing or modifying the slots of null as if it were an array
  • Throwing null as if it were a Throwable value
In this case the second option was the culprit. The Skills panel is initialized before the Stats panel and Skills is giving the Stats variable characterField a value. It would have been possible to remove characterField from Stats and initialize it in Skills instead, but since that variable has nothing to do with the Skills panel that was avoided. Instead the solution was to change the order of the tabbedpanel creation. Stats would be generated first, followed by Skills and then lastly by Equipment.

With that out of the way the listeners for all 210 JComboBoxes in Skills had to be created and then linked to associated int arrays to store the selected data. While time consuming, it wasn't extremely difficult to do. In the end I was also able to put in checks to ensure that a skill wasn't assigned points if it's requirements did not already have points assigned. If that is the case an error message is generated.


This basically finished off the groundwork for the Skills tab. All that is left is to locate the equations that govern each of the 210 skills and create a separate method for each. These equations must be stored somewhere, I'm hoping the good folks at Diabloii.net will be able to point me in the right direction. I'm hoping it is an equation that drives each skill. If not then I'll have to store each skills values in an array of arrays and then create my own equation to generate the necessary information.

Once this is done I'll have a standalone skill calculator ready to go.

Tuesday, November 6, 2007

Java: DII Character Simulator Update #2

The third and final piece of the GUI for the character simulator is completed. This won't be the last page to be made, but for the initial application attempt this will suffice. Thanks to the lessons learned making the Equipment tab the format was much easier to setup with the GroupLayout manager.

I took the LCS of the Diablo II program as a template and then added any information I felt was necessary for display purposes. The first few subpanels were fairly basic, the Misc mods, Mods of note and Resistance panels were for pure display purposes. It was the other panels that required extra components.

Originally I was going to create the Stat panel with JTextFields and have the user enter in the amount of points to add to each characteristic, then a "Calculate" button would need to be pressed to add the needed info. This unfortunately didn't take into account removing points as a user played with the virtual character's setup. So instead I followed the setup of the LCS and used buttons, one plus and one minus, for adding/subtracting stat points. GroupLayout was of course utilized to arrange the JLabels and JButtons into an appropriate order.

This was however only part of the subpanel. There was also the display of the sum of remaining stat points that needed to be added. The subpanel was actually governed not by GroupLayout but by BorderLayout with the GroupLayout section in the center and a FlowLayout in the southern portion containing the JLabel/JTextField combination that displays remaining stat points. The same layout setup was used for the Damage subpanel, with its JComboBox for skill selection component taking up the southern portion of the subpanel.

The last subpanel to be added was the Skill Info section. It occurred to me that there is not a place in the Skill Planner tab to view the properties of each of the skills once points have been allocated. I could have placed a JTextArea at the bottom of the page with this information, but I thought that would ruin the layout of each page. So this feature is added to the Stat panel instead, so that damage and effects of each skill may be viewed, taking into account bonuses from the equipment the virtual character is wearing.


This completes the first phase of the application's development. With the GUI completed I can now begin work implementing listeners and functionality to all of the JComboBoxes, JButtons, JCheckBoxes, JTextFields and JTextAreas. There is a limited amount of pieces that can be tied together before data is required, but as much as possible will be implemented.

Friday, November 2, 2007

Java: DII Character Simulator Update #1

Creating the GUI interface for the DII Character Simulator was the next step in this applications development. Unlike in the original draft I decided against using a JComboBox to change between equipment types. Instead I used a nested JTabbedPane for a more professional look.

Of course this became the first obstacle in that I wasn't sure how to nest a JTabbedPane instead of an already existing JTabbedPane. First attempts lead to the tabs showing up, but in a vertical line instead of horizontally, and also leaving quite a bit of wasted white space on the edges. The problem was that the Equipment class was extending a JPanel, so when this was changed to extend a JTabbedPane everything worked out nicely.

Each piece of the GUI was created in its own method and hosted on a separate JPanel, so that they could be organized and formatted independently. As work began a combination of JCheckBoxes (first time this component has ever been used by me), JButtons, JScrollPanes and JLists (also a first) was organized into the needed GUI pieces. The JList component took some research to locate as the component that would do the job I needed. Set to allow only a single selection, this component is the cornerstone to how equipment will be added (and removed) from the virtual character.

Once all of the components were created, the next task was to combine them all into a single JPanel for display purposes. This turned out to be more of a problem than anticipated. Due to the success of the GroupLayout manager with the skill panels I felt this would be the format needed to create the look and feel of the equipment panels. The problem that arose is that I have only 5 components and didn't want to leave any extra white space. The GroupLayout manager kept cutting off part of one of the components, the ItemList Panel, as I was unable to extend this panel vertically. Everything apparently has to remain in their separate rows, no overlap allowed.

Next attempt was a FlowLayout manager, but getting all of the items to line up vertically simply wasn't working. The components would push each other out of the program window. Finally I settled on a compromise. Two panels were created with the GroupLayout manager that each had two components lined up vertically. The third panel, the one containing the ItemList panel was created with FlowLayout manager. Then all three panels were added to the main panel, also using the FlowLayout manager.


I most likely used more panels and layout managers than necessary, however the final result is quite nice and the code isn't too jumbled, so I'm fine with how things worked out. Once the code was finished for the first equipment type, the helm, it could be carbon copied for all of the other equipment items. The only changes came with the weapon panel, where an option to dual wield was added to the ButtonPanel via a JCheckBox and the other change was the jewelry panel, where some of the selection options were removed or renamed such as elite/exceptional/ normal quality options do not apply.

The next step will be to create the final statistic display that will replace the LCS.

Thursday, November 1, 2007

Java: Hotline Update #4

Yet again more changes to the Hotline program. It is only a single change this time and was done in a previous update so the groundwork has already been laid. Specifically a new button needs to be added. I actually tried to argue against adding this button as once again this will leave blank spots that isn't too pretty. But since no one else seems to be worrying about this I guess I can't either.


In order to add the button a few changes were required. First the OptionPanel required a new JButton to be added, along with its associated listener, and then the GridLayout adjusted to be 6x4 instead of the previous 5x4. What I didn't realize is that by doing so the main frame would need to be extended as well. So originally the button labels were shortened due to not having enough horizontal space to fully display.

The other main change required was to alter the ReportPanel's main If/Else statement to incorporate the new button option. The previous change from the last update now needed a qualifier at the end of its If/Else section:

else if (Integer.parseInt(targetMonth) <> 9 && Integer.parseInt(targetYear) == 2007)

Then the current update could be tacked onto the end of the statement with no qualifier and would only come into play starting November 1st, 2007, which is when it will be introduced to the Call Center.

The only hitch came when call center representatives attempted to open the program after the update. Some received a message stating they could not find the main class. This was resolved by updating the version of Java on their computers to the latest copy.

Monday, October 29, 2007

Java: DII Character Simulator

I've started working on the look & feel portion of the Diablo II character simulator program I mentioned earlier. I'm working on this one piece at a time, as I wanted to get the visual layout accomplished first before putting any functionality into the application.



The layout for the skill calculator portion ended up requiring 2273 lines of code. The main reason for this is that for each character type I needed to create and populate 3 JPanels, 30 JComboBoxes and at least 50 JLabels and then combine them together in a GroupLayout manager to display properly. I decided on the GroupLayout manager due to its versatility, I was able to display the JLabels and JComboBoxes in the format I desired. All of the other layout managers were more restrictive as to where these components could be placed and I was looking for a very specific appearance.
GroupLayout is new as of Java Platform 6 so I needed to update my software a bit. A new JRE was downloaded along with updating my browser shortcut to the API reference, as I was using version 5 up until now. I severely doubt I would have been able to create the application display as I did with any other layout manager, at least not as easily as GroupLayout made the process. There was a bit of a learning curve, as up to this point FlowLayouts and GridLayouts were my managers of choice, but I'm happy with the results.

Each of the character displays is generated in its own method and these methods are the reason for the length of the class file. I am considering separating these methods out into their own class files to cleanup the code to make it more compartmentalized, however I will deal with that once the look & feel portion of the application is accomplished.

Next up, the equipment tab appearance.

Wednesday, October 17, 2007

Java: Concept for DII related application

A while back I saw this post in the DiabloII.net community forum. I really liked the general concept of what the poster was intending to create and thought it would be rather helpful. At the time I was looking for a new Java oriented project and seriously considered starting my own version since the OP was using .NET programming. I decided against it as I didn't want to start a competition between myself and the OP and take away from what the OP was doing.

However it now appears the OP is a bit absent from continuing this project, that and his/her will only work on Windows computers while Java works on all operating systems. So I've decided to try and write my own similar program as there won't be any competition. I won't be telling anyone on the boards until I have some pieces completed. Some of my goals are a bit different and less ambitious so that I have a chance of actually completing it as well.


Above is a concept draft, if you can read my writing of course, of one of the pages of the planned application. Only general layout of the different pages has been seriously considered with some attention to the needed components. I've decided to write the shell of the program first, then add functionality later. The goals of this project are as follows:

1. Search for any normal, set or unique item and equip it to a character (I'm ignoring cracked/damaged/crude items on purpose).
2. Assign appropriate skills to a character and calculate their associated bonus. Basically a skill planner like the German one.
3. Display the true statistics of this character taking into account equipment worn and skills available, to replace the current LCS.

I know I have to deal with rare, magical and runeword items at some point so future goals are:

4. Be able to roll any rare or magical item as if it were dropped ingame, and then equip it to a character.
5. Be able to create any runeword item, while also choosing the base item, and then equip it to a character.
6. Be able to roll any charm as if it were dropped ingame and then place it in character's stash. This includes the Torch and Annilhus.

Obviously 1-3 are going to be done first before I even attempt 4-6. I have general ideas on how to do each part but I need to perform some research in Java to determine the best method. Specifically I need a better information storing method than text files, as used in the AMAS program. There are simply too many mods that can spawn and far too many possible items for text files alone. I'm sure I'll be living in the Statistics forum for a while as well and getting quite a bit of assistance in that regard (never my strong suit when it comes to games). I know this will be a very long project, so wish me luck.

Tuesday, October 16, 2007

Java: AMAS Update #1

After originally making AMAS, I mentioned I wanted to incorporate it into an installer instead of utilizing a zip file. Well I was rather lax on finishing that goal, but in the meantime I was able to make a few updates to the program itself.

Nothing extremely involved. Several spelling corrections to the text for rune descriptions and runewords, as well as adding a few more recipes to the Horadric Cube section. These changes were fairly minor but did put some finishing touches on the program.

The main change for this newest version release is the addition of an installer program. It was created using the CreateInstall Free program, a piece of freeware. There are more advanced versions of this program but for my needs, something simple is all that is required. Now the program is basically complete unless an idea for another section comes to mind. For now though, I consider this program complete.

Friday, October 12, 2007

Java: Hotline Update #3

This time the changes were drastic to the Hotline call tracking program, and so therefore had to be implemented at the beginning of this month rather than mid-month like last time. There were two requested changes; add two more call option buttons and allow the reports to be run over a day's period rather than only by month. The first change was very simple, as that has been done before, the reporting change however was far more complex.

Daily reports is something I considered when originally building Hotline, and even asked those that would run reports if it was a feature they would need. Of course the answer was no, not necessary. Really shouldn't have listened and built the option in anyway.

In order to make this change several things had to be altered. First was creating the new JComboBox for selecting the day range, which was basically a carbon copy of the current code with only minor name changing tweaks. Second was to create the file structure where the report files could be stored on a daily basis rather than monthly. This basically entailed creating 31 folders numbered appropriately 1 - 31. Inside each would be that day's files.

Now that the simple pieces were covered, on to the difficult section. The challenge was implementing this change while still retaining the ability to run reports off of the previous date on a monthly basis. Since the location of these files were different the file location variable (fileLocation) was created and replaced the current static code ("data\\" + year + "\\" + month). Depending on the date of the files requested this variable may have appended on the end the day variable ("\\" + day). For saving the needed files correctly this was the only necessary change, taking the variable fileLocation creation outside of the normal If/Then statement.

if ((year == 2007) && (month <>
fileLocation = "data\\" + year + "\\" + month;
else
fileLocation = "data\\" + year + "\\" + month + "\\" + day;

Now that the files saved correctly, it was time to make sure reports could be run off of them. What had to happen was separating out the report creation instances from those that run monthly to those that would run daily. Before all reporting was dealt with inside of the same If/Then nested statements, now they are worked on separately with a return call at the end of each statement. This way the calls to run reports on monthly dates could be done first and the IF statements for the daily report runs could be simplified. For example:

if (targetFile.equals(TECH) && Integer.parseInt(targetYear) == 2007 && Integer.parseInt
(targetMonth) <>

for the monthly report on technical only calls. The clarifying If/Then statement for the daily reports could then be written simply as:

if (targetFile.equals(TECH))

Then it was only a matter of adding a For loop that would tally all of the reports for the covered date range one at a time and input their information into an array.


Before this update when a file was not present, such as when a representative was out of the office, the report would provide an error message informing the user of this fact.

For a report run over a months time this message appeared maybe once in four months. But now that the report can be run over a shorter date range this message could appear quite often. As a result any such messages stating a file is missing were removed, the only messages retained were those that pointed out errors that would not allow the report to run, such as no month was selected.

There has been some talk of removing some of the buttons, which hasn't been done yet. I can see this requiring me to permanently assign certain variables to buttons to avoid reusing any variables and therefore avoiding combining data for the two buttons into a single report. I don't see that being difficult, it would just require a little effort to keep track of which variables belong to which call type. Something to deal with when we cross that bridge, not beforehand.

Wednesday, September 12, 2007

Diablo II: Plague Javelin / Lightning Fury Javazon Skill Layout

Guides for Amazons using Plague Javelin and Lightning Fury are not very abundant. There is one guide for PvP play, but none I could find that covered PvM specifically, although this guide would do fine in that regard.

The skill setup is as follows:

Jab - 1
Pierce - 1
Poison Javelin - 20
Plague Javelin - 20
Lightning Fury - 20
Valkyrie - 20

Valkyrie doesn't have to be maxed, but since I prefer a more durable tank and there isn't anywhere else to place the extra skillpoints they go into valkyrie. I like to provide a breakdown of when the points were allocated:

Jab - 1
Critical Strike - 1
Dodge - 1
Lightning Bolt - 1
Avoid - 1
Poison Javelin - 7

This brings us to character level 12 and Poison Javelin is doing decent damage, just very slowly. This is where the character is throwing javelins and then running around the screen for several seconds while the poisoned monsters chase her until they expire. The going is slow but steady.

Poison Javelin - 10
Inner Sight - 1
Slow Missile - 1
Plague Javelin - 1

At level 18 Plague Javelin finally becomes available and the damage output increases more sharply from here onwards. Plague Javelin also has a shorter poison length, causing the monsters to fall quicker and requiring less running around evading monster packs. At level 18 Andariel will be encountered; the catacombs will be a cakewalk compared to facing her.

Plague Javelin - 7
Evade - 1

Now at level 24 each point into Plague Javelin causes the monsters to fall faster and faster and most of Act II will be fairly simple, especially now with an Act II Desert mercenary to tank for the character. No longer does the character need to run away from monsters, simply let them swarm the mercenary and throw a javelin from time to time.

Decoy - 1
Plague Javelin - 13
Valkyrie - 1

At level 30 the ultimate tank becomes available, Valkyrie, taking some of the heat off of the mercenary and making the Act bosses much easier to deal with. At this point a desert mercenary is no longer required and and Act I or III mercenary may be hired for additional elemental damage.

Plague Javelin - 20

At level 37 Plague Javelin is maxed. It is doing a respectable amount of damage and monsters are starting to fall in one javelin throw, a theme that will continue through the first few Acts of Hell.

Valkyrie - 10
Penetrate - 1
Pierce - 1
Poison Javelin - 20

At level 56 Plague Javelin and its synergy are maxed, making a formidable weapon for the character. Poison resistant and immune monsters are starting to be encountered, so a backup is now needed.

Lightning Fury - 20

At level 74 all offensive skills are maxed and monster packs fall very quickly. An initial Plague Javelin is followed up by a few Lightning Fury strikes to eliminate the majority of the monsters, the few remaining ones succumb to poison soon afterwards. Bosses are still going to be difficult as neither offensive skills is designed for single opponents so the fights will be long. This is why it is better not to have a melee mercenary, the ranged ones last much longer and this saves resurrection fees.

Valkyrie - 20

By level 81 all of the skills are maxed. With plus skill bonuses the valkyrie should have around 3000 life, more than enough to tank almost anything in the game. The general gameplay for normal monsters is to allow them to surround the valkyrie and then use either Plague Javelin or Lightning Fury, depending on which type of immunity the monsters posses. Single monsters can be dealt with either a combination of the valkyrie, rogue mercenary and Jab or a single Plague Javelin. The only monsters that are immune to both offensive skills are the Black Souls of the WSK and monster bosses. This is where the rogue mercenary with elemental damage is extremely useful, equip her with a fast bow and she'll make short work of the souls, especially with the valkyrie drawing all of their fire.

For this type of build there aren't any equipment pieces that are vital, only a few that make progress much simpler. Titan's Revenge for a weapon and Trang's Gloves are the only two pieces that make a large impact to the effectiveness of this character. Questing is still possible without them, but the progress will be much slower and require far more patience and trips back to town. All other equipment is subjective to the player's playing style.

Tuesday, September 11, 2007

Diablo II: Matriarch Chiana

In a recent tournament I played a Plague Javelin / Lightning Fury Amazon. Due to extremely poor planning on my part, in other words no planning whatsoever, she had to drop out of the tournament. The restrictions of the competition required me to use elite gear in Hell, where I didn't meet the requirements to equip such gear. An hour clearing out the Blood Moor naked convinced me it wasn't worth the effort to continue, so I retired.

This travesty of course demanded some sort of redemption on my part, so Chiana was born. Played over the span of six months, due to interruptions to play additional tournaments, Chiana slogged her way to become a Matriarch. A few personal rules are put in place to keep the game interesting, namely that all characters are untwinkled unless a weapon is required to continue questing. Only when Hell is reached may items be twinkled on. This is to ensure no character becomes boring due to the ease of Normal/NM and that tactics are learned in these earlier levels to be used in Hell when they are truly needed.

The journey started off rather slow for Chiana, since Poison Javelin isn't the most damaging spell considering its time requirement. This means she was poking monsters with her starter javelin for quite a while or throwing Poison Javelins and then running around the screen wildly while poisoned monsters chased her. None of the normal monsters posed much of a threat to Chiana, only the act bosses and even then it wasn't so much a fear of death as length of time required to win the duel. For example Andariel eliminated the mercenary with a poison shot early and proceeded to chase Chiana round and round the blood pit in the second room. All the while Chiana would stop from time to time to throw Poison Javelins at Andariel and then continue running around the blood pool a bit more. The same tactics were used against all Normal and Nightmare bosses.

Hell was a different story, which was run at /p1 instead of the /p8 previously used. Chiana and her cold rogue mercenary was able to be twinkled at this point to offset the severely increased challenge that this difficulty produced. Progress was actually quicker in Hell than Normal / Nightmare due to the fact Plague Javelin and Lightning Fury were both maxed. I never quite understood why everyone was excited about Lightning Fury Amazons, I preferred to use Charged Strike / Lightning Strike instead. Now watching how quickly packs can be dealt with using LF I finally understand.

Nothing really withstood Chiana until she ran into very nasty stair trap in the Kurast Bazaar. Upon entering one of the temples she was greeted with triple boss back; 2 Wailing Beasts and 1 Black Rogue with one of the Wailing Beasts having the Fanaticism aura. She got off a few LF shots and a single PJ throw before being put into stun lock and then...death. I determined that a few PJ throws would finish off the rest; simply pop in, throw a javelin and then pop out. Well apparently I forgot that all my equipment was lying on the ground in the temple as Chiana popped in and for some reason couldn't throw a PJ. I was very confused when she died again, until I saw her spawn at the docks and she wasn't holding a javelin....oops. A quick purchase at the local store solved that issue and the remaining monsters were dealt with.

All other monsters and bosses were dealt with fairly easily, until Baal was encountered. The fight with Baal was an epic battle worth of song, dance and much consumption of recreational beverages. For fifteen grueling minutes Baal, his clone, Chiana, her rogue companion and the valkyrie slugged it out. Baal remained cloned for most of the battle, but Chiana was not to be intimidated and refused to retreat. As a result frost cones, mana draining breath and festering appendages filled the screen continuously. Chiana was actually able to keep her rogue companion alive for most of the battle, although I'm unsure how helpful she was overall. Plague Javelins slowly drained Baal's life while he and his clone teleported all over the chamber unleashing deadly havoc. Eventually he fell and Chiana gained her Matriarch title.

Stats:
Level 83
Strength - 50 (80)
Dexterity - 103 (141)
Vitality - 337 (337)
Energy - 15 (25)

Life - 1225 (1301)
Mana - 138 (221)

Lightning Resistance - 75
Fire Resistance - 75
Cold Resistance - 57
Poison Resistance - 63

Skills:
Jab - 1 (11)
Poison Javelin - 20 (30)
Plague Javelin - 20 (30)
Lightning Fury - 20 (30)
Pierce - 1 (9)
Valkyrie - 20 (28)
Decoy - 4 (12)

Equipment:
Weapon: Titan's Revenge
Armor: Skin of the Vipermagi (socketed with Pruby)
Shield: Lidless Wall (socketed with Pdiamond)
Boots: Fire Resist +40%, Lightning Resist +26%
Belt: Razortail
Gloves: Trang-Oul's Claws
Helm: +10 to Strength, +38 to Life, +101 to Attack Rating, All Resistances +17, +2 to Amazon Skill Levels, Poison Length Reduced by 75% (socketed with Pruby)
Ring 1: Lightning Resist +28%
Ring 2: Cold Resist +21%, Poison Resist +23%, 3% Mana stolen per hit
Amulet: +50 to Mana, Poison Resist +5%, 5% Mana stolen per hit, +2 to Amazon Skill Levels

Mercenary:
Helm: Tal Rasha's Horadric Crest
Armor: The Spirit Shroud
Weapon: Goldstrike Arch

Thursday, August 30, 2007

Java: Hotline Update #2

This time around the update was very simple. No new buttons required so this meant I didn't have to add to that massive if-then statement in the reports section with another clarifying statement.

Instead the only update required was to add the name of the new Customer Service representative so that he could utilize the program. This required me to add a new variable to the repString String array so that his name appeared in the JComboBox drop-down menu. Along with this changes were also made to the ReportPanel file. A new variable was added to the repNames and techNames String arrays along with the corresponding JRadioButton for selecting the report type. Other than this the only necessary changes were updating the Listeners to incorporate the new variables.

At first I thought this update was going to have to take place at the beginning of next month, just like the last one. However since no additional call options are being added I didn't have to alter any of the existing reports, only create a new one for the new Customer Service representative.

Monday, August 6, 2007

Diablo II: All Alone Tournament III

The concept of an All Alone Tournament is that the character cannot enter town or talk to anyone unless it is necessary to continue questing. This means quest rewards such as the Charsi imbue reward, Larzuk socket reward or Akara skill point reward are not obtainable. Also since it is not possible to go back to town no mercenary is available to the character and equipment cannot be repaired in the normal fashion nor potions bought. Living off of the land is the name of the game.

I decided to play a Necromancer summoner, even though my last (and first) one was a bit boring. I wanted something other than the lightning sorceress I seem to always play in tournaments. I needed a character that wasn't too mana intensive since pots cannot be bought and also a character that wasn't dependent on the durability of their items, in other words a melee character.

I did see a few problems that may occur, mainly getting that first monster corpse to begin building my army. In the beginning I was able to use a bow along with a clay golem, but this only worked for Normal. Once in Nightmare I had to switch to using curses such as Attract, Iron Maiden and Amplify Damage to get the army going. It was slower and required a few mana potions but still possible. However once I got to Hell it required a good 15 minutes and a majority of my mana pots to create my first army in the Blood Moor. After that I decided to not close down the game session and simply paused the game between playing sessions. This meant I didn't have to raise an army again, but also that muling off any interesting finds was not possible.

Even without a mercenary this character was faster than my twinkled one from before. I'm thinking I was not playing correctly the first time and that were I to create another twinkled character it would be about as enjoyable as this one.

I was fairly satisfied with how well I did, getting all the way to Act II of Hell and level 75 before deeds were encountered. Especially since my resistances were terrible:

Cold: -64%
Lightning: 5%
Fire: 23%
Poison: 50%

I decided to not go the normal route of getting revives since they are so mana intensive. Instead I put extra points into Clay Golem to ensure it was more durable during the initial army gathering stage and then I dumped points into Skeleton Mage for more soldiers. Mages aren't the most effective minions, but they are extra shields for my character, Anubis, to soak up elemental damage and they did come in quite handy in tight areas where only single skeleton could attack at a time. At the time of Anubis' demise he had 10 skeleton warriors, 7 skeleton mages and a clay golem at his disposal. I believe were I to make another Fishymancer I would go this route again with a single point in Revive as well.

This will be the last tournament for me for a while as I want to concentrate on my Softcore characters. I have only a single matriarch/patriarch since my restart a few months ago. I'm going to get back to my poison Javazon for now so I can utilize all these nice items found during the MFO.

Thursday, July 26, 2007

Diablo II: Meteorb Skill Layout

This should have been posted when Malice became a Matriarch, but better late than never. Guides on how to build a Meteorb in Diablo II have been done and redone to death, however this is an explanation on how I built my current magic finder and how she is used.

The skill setup is very traditional:

Frozen Orb - 20
Meteor - 20
Fireball - 20
Fire Mastery - 20
Static Field - 1
Teleport - 1
Warmth - 1
Cold Mastery - 1+

However I like to provide a breakdown of when the points were allocated:

Warmth - 1
Firebolt - 1
Static Field - 1
Fireball - 1

This will bring us to character level 12. Static Field is used only on unique boss monsters while Fireball has become the main skill, replacing Firebolt. From here onward we'll be trying to max out Fireball to level 18, which bring us to character level 29 with some points saved up to obtain Frozen Orb.

Fireball - 19
Fire Mastery - 1
Ice Bolt - 1
Ice Blast - 1
Frost Nova - 1
Glacial Spike - 1
Blizzard - 1
Frozen Orb - 1
Cold Mastery - 1

At character level 30 Frozen Orb becomes the main skill with Fireball as a backup for Act bosses.

Frozen Orb - 2
Fireball - 20

Fireball is now maxed, time for Frozen Orb now.

Frozen Orb - 20
Telekinesis - 1
Teleport - 1

This brings us to character level 49, still in Act I of Nightmare. At this point everything becomes rather simple. Spam Frozen Orb until all monsters are dead since there aren't any immunes yet. Act bosses should still be weakened with Static Field before finishing them off with Frozen Orb.

Inferno - 1
Blaze - 1
Firewall - 1
Meteor - 20

At character level 68 Meteor has been introduced to the character's arsenal. It's uses are rather limited in Nightmare due to Frozen Orb's power, but it will come into play later on in Hell. It does however synergize with Fireball nicely to add some punch to that spell.

Fire Mastery - 20

This is basically all that is left to max until the character has completed questing, at level 83. From this point onward Cold Mastery is what should be maximized to increase the killing power of Frozen Orb for general magic finding purposes.

In Hell Fireball replaced Frozen Orb as the main killing spell. However Frozen Orb is used to chill/slow the monsters before Fireball is spammed to finish them off. For normal monsters Meteor is only used for stationary(ish) targets, such as those the mercenary is tanking or Unravellers.

Act bosses are dealt with fairly simply. First use a Frozen Orb to chill them and their minions, then Static Field to cut their health in half. Then hit them with Meteors and Fireballs until finished off. Since Meteor is a timed spell normally 2-3 Fireballs can be launched in between Meteor casts.

Any area or boss can be run with this build, even the Countess due to her cold/fire dual immunity as long as a powerful mercenary is present. She's especially good at Andariel, Mephisto and Pindleskin runs. Since these are the main boss runs for magic finding, equipping any future characters is a simple matter.

Tuesday, July 24, 2007

Java: En Guard Update #3

A bug came up recently in the En Guard program that allowed a representative to save a record without filling in the information as to which rep took the call and what platform the problem occurred on.

The fix itself was rather simple as there is already a check to ensure that the other fields (contact name, number, subscriber number) are filled in.

if ((tempNumber.compareTo("") == 0) || (name.compareTo("") == 0) || (input.compareTo("") == 0) || (contact.compareTo("") == 0))
JOptionPane.showMessageDialog(recordPanel, "Please fill in all fields before saving record.", "Incomplete Record", JOptionPane.ERROR_MESSAGE);

In order to include the two additional fields the compound OR statement needed to be expanded.

if ((tempNumber.compareTo("") == 0) || (name.compareTo("") == 0) || (input.compareTo("") == 0) || (contact.compareTo("") == 0) || (platformBox.getSelectedIndex() == 0) || (repBox.getSelectedIndex() == 0))

PlatformBox and RepBox are the JComboBox variables for the two associated fields. If their currently selected option is the initial value of a blank space then the statements will be true and the record will not be saved.

Originally I thought I would need to create another variable or two to track when the selected index of either JComboBox changed, but the getSelectedIndex() method made things so much simpler. Hopefully no other changes will need to be made to the En Guard program as this is the only report of an issue within the past three months.

Friday, July 20, 2007

Diablo II: Magic Find Olympics

The Magic Find Olympics (MFO) is a contest run twice a year on the Single Player Diablo II forum. The basic premise is that each contestant picks something to run: Baal, Mephisto, Level 85 areas or Super Uniques. Then everyone has nine days to run those areas as much as possible, the person with the best items found wins their respective section and can then take a few items from the losers.

I joined this with my one and only magic finder, Malice. In preparation for the tournament I leveled her from 83 to 88 in both the Pits and World Stone Keep (WSK). This was to make her more powerful, her mercenary better able to survive when tanking Mephisto and in search of a four open socket Monarch shield in order to make a Spirit runeword. On my very last Pit run before the tournament a zero socket Monarch dropped, so I used Malice's Hell difficulty socket quest reward to turn it into a mid level Spirit shield.

Then the games were on:

Sign-up Thread
Progress Thread
Results Thread
Meet the Olympians Thread


I ended up 7th in the Mephisto category, the winner actually took a week of vacation to participate so I didn't have a chance as I was only magic finding when I had free time instead of all day long. Overall here are some numbers of my participation:

201 qualifiers
2091 runs completed
10.4 runs per qualifier
39 hours 55 minutes 41 seconds spent overall

Each Mephisto run started off taking 74.35 seconds per each run. For each run I start in Act IV, use the Waypoint (WP) to Act III Durance Level 2 and then teleport to Mephisto. Once Mephisto is eliminated pick up my winnings, use a Town Portal (TP) to Act III town, visit Cain to identify the items and then Ormus to restock on potions and sell unneeded items. Then return via the WP to Act IV and quit the game. Rinse and repeat.

Obviously this is rather time consuming and as I played better ways were found that shortened the running time to 60.6 seconds per run. First was re-rolling the map to look more like this one, where only four teleports are required to reach level 3 of the Durance rather than the 12 I was using before. Also apparently it is possible to active a WP with the Telekinesis spell rather than having to walk/run to each one. These changes shaved 14 seconds off of my time and make the runs more effective, which became apparently when my best two drops occurred in the last two days of the tournament.

Overall it was fun, but a bit draining. I'm sure I won't be running Mephisto again anytime soon. Not only because I'm sick of seeing him but also because I have the vast majority of times he can drop in duplicate so the rewards wouldn't be very good. There won't be another one for six months so we'll see at that time if I partake again or not.

Monday, July 9, 2007

Diablo II: Six of One, Half Dozen of Another Tournament

Going a bit into the past here, but this was the very first tournament that I joined in the DiabloII Single Player Forum. The basic premise of this tournament is that your character can only be equipped with items that have a multiple of six in their description, anywhere in the description. At first this sounds very limiting, but as you get to playing you'll find that such items fall at a fairly regular pace.

Devils_Advocate was a lightning sorceress, a fairly overpowered build that I got rather good at on Battle.net. She's simply to play and since magic finding and rerunning of areas was allowed in this tournament the perfect character.

Questing through Normal and Nightmare was simple enough, some Near Death Experiences (NDE) were encountered but nothing to serious. Quite a bit of MFing was required in NM before moving onward to Hell, where things got very interesting. The going was rather slow in Hell, but I was able to get all the way to Act V before the guest monsters got the best of me. Encountered a pack that eliminated the mercenary and I panicked, which lead to deeds.

Regardless I see this as a successful tournament, not just because I ended up winning with the highest overall score either. This was my very first Hardcore character and I learned quite a bit that should help me with other tournaments, as well as my normal Softcore characters.

Wednesday, June 27, 2007

Java: Hotline Update

Apparently I get to now experience what programmers worldwide already know, those in charge of a program's content like to add all sorts of features without regard for how this will affect the coding of the program itself. I had confirmed that the call options were static and would not change, but apparently that is not the case.

Five additional call options needed to be added to Hotline along with removing a representative's name and adding an additional reporting option. Obviously, removing the rep's name was by far the easiest of all the changes needed, this just required altering a few variables and removing a few lines of code. This did not change any functionality of the program, unlike the other changes that needed to be made.

Adding the five new buttons, each one representing a call type, was not much more involved. New variables needed to be added and then listeners associated with those JButton variables defined. Once this was set it was only a matter of arranging the new buttons to make logical sense, and then resetting the grid layout to incorporate those new buttons. Unfortunately I was unable to convince the others to leave the number of possible buttons at a decent numbers, such as fifteen or sixteen, so instead they settled on seventeen. This makes the program look a little chunky due to the wasted space at the bottom, but it is only a visual issue and not a functionality problem.

The problem with adding new call options after the program went live to the call center is that now the files for June are formatted one way, and the files for July another. Running a report for one month has to be done differently than the report for the other as a result. Due to the changes a few variables must change value for each report type. Instead of rewriting the reporting call and having a separate call for each month I decided to use an If-Else statement to set the values of those variables. If the month being reported is June then the variables are set to deal with a twelve call option file, otherwise they are set to deal with a seventeen call option file.

Finally a new report was required that would acquire the total values for two types of calls, labeled as technical calls, and display those values in the JTextArea. This was needed by the tech group for month end reporting purposes. Thankfully the location of these buttons didn't change from the twelve to seventeen option frame so the same call would obtain the necessary information from each file due to it being in the exact same location.

With these changes the program itself is ready to be re-released to the call center starting in July. Hopefully no major changes will be needed for August, but at least the groundwork is laid to make these changes much easier to accomplish.

Tuesday, June 26, 2007

Diablo II: The Afterlife Tournament

The Single Player forum of Diabloii.net is a lively place where various amounts of tournaments are constantly in progress. The one I joined recently was The Afterlife Tournament. The basic premise behind this tournament is that the only items that can be worn are ethereal items or a set/unique item dropped by an act boss. This of course meant that my character, Angela, had to start life punching all of the monsters until she could use her skills. This would be something I've never had to try before.

As expected resistances were a major problem in this tournament, mine were fairly low until Act V when I was able to create an Ancient's Pledge shield (~50% resistance to all). However since I picked a lightning sorceress as my character dealing damage wasn't a problem in both Normal and Nightmare difficulties. Some near death experiences (NDE) were encountered, normally a result of the lack of resistances. However in the end it was not resistances that killed me but impatience. In the Sewers of the Kurast Baazar (Act III NM) I encountered a pack of dolls that suicide bombed Angela, as described in my death post.

Were I not so impatient then I could realistically have gotten this character to Hell, however I don't believe I would have made her a guardian. I normally play softcore so dying is just something that happens from time to time, but in tournaments hardcore is the only option and one death equals elimination. I'm bound to make a stupid mistake somewhere along the way, so I never expect to actually win a tournament but they are fun regardless.

Thursday, June 7, 2007

Utility: GoldIcon

While I do enjoy creating the programs in Java for work and myself personally, opening them in a DOS prompt is not the most convenient process. Obviously I could simply combine all of the class files into a jar executable, but then all of those files would look identical. This would make things difficult for my coworkers who are utilizing the icons and also simply looks unprofessional. So I use GoldIcon to create all of my icons, it's a freeware program I found while googling for such applications online.
The program itself is extremely simplistic and used only for creating the icon itself, not the executable. This make it perfect for me since my artistic skills are extremely limited. Simply use the cursor to click one of the boxes to place the appropriate color in that position. It is also possible to create shapes (circles and rectangles) automatically.

My icons started very simple, such as a colored box or hourglass figure. I also had a lot of fun creating different shield crests, one of which is now being used for the En Guard program (it seemed fitting). Below you can see some icons that I have created to date.


Not all of these icons are in use. It would be too confusing to have 4-5 shield icons for different programs. Besides, variety is the spice of life, is it not?

Thursday, May 31, 2007

Java: Hotline

From time to time in the call center at work we track the types of incoming calls to determine what new information we need to be providing on our website and marketing material. In the past we've used sheets of paper and placed tick marks under headings to record this information. Then the marks are tallied up at the end of the month for reporting purposes. Obviously a very manual and time intensive process, but since it is done only one month at a time not a massive issue. However now we want to track a bit more consistently so a better process is needed.

And so Hotline was born. It is designed to be very user friendly and also extremely quick to utilize, as the call representatives don't have a lot of time to be entering any notes into the system in between calls. So this is a very high level tracking system to get a general feel for what types of calls are inbound. There are two parts to the system; the call tracking side and the reporting side. The call tracking side is simply a series of buttons, one for each possible call type. When a button is pressed a pop-up message appears confirming this fact, acting as a deterrent to any accidental double-clicking as only one option should be selected per call. This will then update a text file saved on the server named according to the value in the Representative JComboBox.

The reporting side of the system was a bit more difficult to setup. The information is saved in text files as strings, so updating the information due to an incoming call relies heavily on converting part of these strings to an integer, increasing the number then converting it back to a string to insert back into the text file. For a report run on a particular representative the process is straightforward. The month selected in the JComboBoxes is located and the particular representative's file in this location is opened and its text dumped into the JTextArea.

A report run containing information for all of the representatives is a bit more involved. Each representative's file is opened individually and the values for the number of calls taken are saved into an array of strings. This string array is then converted to an integer array. The process is then repeated for each representative's file and the new call value added to the current one in the integer array. Eventually all of the information is compiled. Then the array of integers is converted back into an array of strings and these strings appended together to create the output report in the JTextArea.

Originally I was going to make the reporting call a JMenuItem instead of its own JTabbedPane, however that was becoming a bit too cumbersome. Any changes needed in the future would be more difficult with all of the reporting code in the same java file as the button panel code. So they were split apart into separate JTabbedPanes for my peace of mind. Also, some of the values are hard coded into the program, specifically the representative's names and the month/year values. Any changes that are made would require the entire program to be compiled again and a replacement executable generated. Eventually I may make these values editable by anyone, but for now the program is ready to be pushed out to the call center.

Friday, May 25, 2007

Java: CME Log Date Decoder

At work we recently, as in the past two years, updated our CD-ROM application from being a 16-bit Toolbook program to purely Java based. Along with this massive change many features were updated and revised. One such feature is the CME (Continuing Medical Education) credit tracking system. Before the update, CME was tracked in a text file on the hard drive by date. Each article viewed in the program would have it's own line in this text file and a Gregorian date would be prominently displayed for that article.

Now with the upgrade to Java things have changed. No longer is a date available to the naked eye when reviewing the logs. While each article still does have a date attached, this date is in milliseconds. And to make things slightly more complicated these are milliseconds since January 1st, 1970. Why that date was chosen I do not know.

So for our Customer Service department this poses a bit of a dilemma. They are charged with receiving these CME logs in paper format and having to determine what date to assign the CME credit. Only recently has this problem come to light, and to combat it I created a small program to automatically calculate the Gregorian date from the given millisecond variable.

The CME Log Date Decoder program is a modified version of the Password of the Day program. It will take as input the time in milliseconds, which will be a string variable as far as the program is concerned. This variable first needs to be saved into an array of strings, one bucket for each character, then converted into an array of integers. As integers each array bucket is put through an algorithm and then summed together and added to a Calendar date of 1/1/1970 in order to obtain the correct CME log date in Gregorian format. This is then displayed to the user. The program requires almost zero memory so the calculations take less than a second to perform.