This is a wiki for a reason. Anyone can contribute. If you see something that is inaccurate or can be improved, don't ask that it be fixed--just improve it.
[ Disclaimer, Create new user --- Wiki markup help, Install P99 ]

Non-Classic Compendium

From Project 1999 Wiki
Jump to: navigation, search

Contents

Introduction

This page documents the various aspects of Project 1999 which are not classic (ie. the same as they were on live).

Early Exploit Fixes

Green and Teal have introduced a variety of unclassic changes. The staff generally classifies/justifies all of these changes as "exploit fixes":

  • Whirl Till You Hurl was incredibly overpowered on live (it could be used to kill reds into the 30s), and has only it's latter (nerfed) version on Project 1999

Technical Constraints

Titanium Client Limitations

The developers originally decided to use the Titanium client as the basis for Project 1999 many years ago. While this decision allowed them to make Project 1999 what it is today, it also prevented them from fixing certain unclassic issues. It is unlikely that these issues will ever be corrected on Project 1999:

  • Unclassic UI
    • The Titanium client offers a vastly more configurable user interface than the one available during the classic era.
    • NOTE: Despite the above however, and despite many thinking that the (Green) UI isn't classic, it's actually extremely close to the classic UI ... it's just that many players in classic never hit F10, and so never saw that version of it.
  • Limit to number of open bags
    • In the classic era only two bags could be opened at once, but the Titanium client allows all bags to be opened simultaneously.
  • Races with poor night vision see "too well" in dark conditions
    • To make the game easier the developers of EverQuest improved the night vision of races that (in the classic era) had poor night vision (ie Humans, Erudites, and Barbarians). Because vision is controlled entirely by the client, there is little (or likely nothing) the staff can do to restore the original racial vision limits. This has since changed with the release of the Green server where the Gamma option no longer works, only being stuck at the darkest option.
  • Stamina/endurance doesn't work properly
    • Stamina/endurance was changed to work differently in EverQuest after the classic period (December 18, 2003 patch), and the Titanium client assumes that that change has happened. As a result it is difficult (impossible?) to re-create truly classic stamina/endurance behavior with the Titanium client.
  • Spell scribe speed is "too fast"
    • "Scribing new spells should take a lot longer, and memorizing spells also took longer depending on your level and the level of the spell being memorized. This is a known issue, but cannot be fixed at this time due to client limitations."
      - Developer Telin
  • Mana recovery behaves strangely
    • This issue is particularly relevant for Shaman who "cann-dance". On live every "tick" your mana would go up ... and that would be it. However on Project 1999 your mana goes up, then down, then back up. This is because EverQuest changed the rate of mana recovery after the classic era, and so the Titanium client is "calibrated" to that rate of recovery. Every tick Project 1999 has to correct the client, creating the up/down/up phenomena.
  • Unable to swim up Nurga waterfall
    • On live players were able to swim up the waterfall at the Mines of Nurga entrancereference?
  • Unable to "glitch" through the locked Hole door
    • On live all players could (with effort) swim through the crack in the locked door to The Hole (in Paineel), but on Project 1999 only smaller races (or characters shrunk with a potion) can.reference?

Non-Client (Staff-Based) Technical Limitations

Some differences on Project 1999 area because of technical constraints that aren't caused by the Titanium Client. Another critical difference between the Project and live EQ is that Project 1999 has an all-volunteer staff, not a paid one, and thus it can't solve as many problems as (paid) live GMs could. For instance, live GMs could afford to spend time fishing out players who fall off boats, while Project 1999 instead makes classic compromises to avoid having those players fall off in the first place.

Boats

As it turns out, coding boats is extremely tricky (even Verant had some issues with them). To ensure boats function properly on Project 1999, the developers were forced to make some unclassic compromises, specifically:

  • Project 1999 uses different boat models than the classic ones
  • Boats on Project 1999 sometimes path differently than boats on live.
  • When you board a boat on Project 1999, you are temporarily given levitate for as long as you remain on the boat (and roughly one second afterwards).
    • This temporary levitation prevents characters from falling off boats accidentally (and thus prevents petitions).

Coins

On live it was possible to drop coins (money) on the ground, but it is not possible here. Technically this change did happen on Live EverQuest also (see [1]), but it came just before Luclin released (7 November 2001 patch). It was implemented "early" here to avoid issues malicious player behavior, such as players tricking others into dropping coin, or trading money in an untraceable way for RMT.

Intentional Changes

Project 1999 team has decided to intentionally make these changes from EverQuest classic era.

Classic Environment

Whenever there is a conflict between classic mechanics and a classic environment, the P99 developers almost always choose classic mechanics. This is why some item recharging, epic item multi-quests, and the widespread use of items like the Worker Sledgemallet (which is usually acquired through charming rather than through the Protect the Shipyard quest) exists on Project 1999, even though few players if any remember those mechanics being used when they played during the classic period. Because all of those mechanics technically existed on live during the classic era Project 1999 supports them.

However, with all that being said there are still rare occasions when the developers will do something which supports a classic environment over the correct classic mechanics:

Exact Mechanics/Formula

Since no one but Verant knew the exact formulas for how EverQuest worked (and even they no longer do, as the classic server code has been lost) all calculations on Project 1999 are the developers' best approximation, based on logs, videos, and other sources from the classic era, as well as non-classic sources (eg. EQ Mac, Live) which are believed to have parts that still work the same way they did in the classic era.

ZEM (Zone Experience Modifiers)

A key exception to this are the Project 1999 Zone Experience Modifiers. As explained in this thread, the commonly known ShowEQ values are based on a client data dump from 2003 ... which means that (many of them) aren't classic. However, there is some other classic evidence of the actual classic ZEMs of zones, and as evidence of such ZEMs surfaces the P99 development team updates them to be more classic. Even after over a decade, new research is still being found and (presumably) will still be incorporated by the development team.

Exact Spawn Patterns/Paths

As much as possible the exact spawn locations/paths/patterns of "regular" mobs are identical on Project 1999, but of course the devs couldn't find exact evidence for every mob, and so many had to be added using their best guess. The exact live spawn patterns/paths of many "special" mobs (eg. Quillmane, the Ancient Cyclops, or Pyzjn) are known ... but they weren't known to players on live. Thus, the developers of Project 1999 have set these mobs to have different spawning patterns that are unique to this server, and those patterns are sometimes (rarely) even updated to provide further "classic mystery".

25 mob AoE limit

On live AoE spells (and Bard songs) could affect all mobs in range, but on Project 1999 these spells/songs only affect a maximum of 25 mobs. There are a few explanations for why the developers made this "unclassic" change:

  1. GM sanity: petitions for zones where AoE was widespread (eg. The Overthere) were far more common than petitions for other zones. Since P99 has an all volunteer staff, this drain on resources was significant
  2. The entire zone of Chardok was monopolized by AoE groups, to the point where it was difficult for non-AoE adventures to level there (creating an extremely unclassic environment in that zone)
  3. During the original live classic era (1999-2001) internet connections were much less reliable, both in terms of bandwidth and in terms of latency/ping. While some players did have access to better connections, the vast majority of EQ players in the classic era were constrained by their internet connection, and this limit simulates that limitation on Project 1999

Epic level requirements

It is unclear whether or not all epics on live required a specific level to equip/use, but on Project 1999 all epics require level 46. "With the next patch, all epics will have a level 46 requirement.
There is inconsistent research regarding which epics required level requirements to obtain. Several couldn't be completed until 46 or higher due to level checks on quests or certain steps involving planar zones. It has been noted by the original developers that epic items were intended only for those of higher levels. Additionally, we feel that acquiring an epic weapon should only be possible when a player has become powerful enough to cross interplanar portals. Therefore, we are adding a level requirement of 46 to equip all epic items." - Project Manager Nilbog

Seafury Cyclops Drop Rate

Many players remember the Seafury Cyclops (in Ocean of Tears) dropping gems and other valuable items more frequently than they currently do on Project 1999. However, drop rates are hard to measure (one would need logs from a significant number of Seafury kills during the classic era), so it's hard to say for certain whether this change was classic or not. Two possibilities have been floated:

  1. It is classic: a player with logs from the classic period submitted them to the devs, and the devs adjusted (ie. "nerfed") the Seafury drop rate to match
  2. It isn't classic, but was needed for staff sanity: "Seafury Island" was another location that created an excessive number of petitions, as many players competed for the Seafuries valuables. It is possible that (as with the 25 mob AoE limit) that the developers simply made this change to free up (all volunteer) support resources.

/consent allows looting

Until the July 20, 2000 patch on live, players were able to loot other players' corpses when given /consent. This ability was nerfed due to CSR problems caused by players fraudulently offering to help drag a corpse but stealing items instead. P99 devs presumably always left this nerf condition in place on p99 for the same reasons.

GM Events

Because Project 1999 does not have a paid customer service team of GMs and Guides (as Live did), they are not able to hold GM events with the same frequency and/or detail as the events on live. Thus, GM events are intentionally unclassic here. For a listing of items awarded during GM events on live but not known to exist on p99, see Players:GM Events.

Simulated Raid Mob Re-Pops

1-3 times a month (at randomly determined dates/times) Project 1999 spawns all raid mobs at once (and gives all players a message about an earthquake occurring). This did not happen on the live Everquest servers. However, the live servers would often be taken down temporarily for servicing, which had a similar effect. Project 1999 players get the benefit of these events without the inconvenience of their server being taken down, as explained in this posting from head developer Nilbog:

Starting this month, there will be two simulated respawns occurring at random dates/times. These repops are designed to fill in the gaps of missing chances of rare npcs and raid targets from patches and downtimes which frequently occurred in the classic timeline. At the beginning of each month, I will roll two random dates and times. It might be early in the morning, early in the evening, or directly in prime time; it is completely random. I believe random is the fairest way to accommodate players in all time zones.

It has been a little over a year since the simulated respawn system was put into place. I believe this has been a mostly positive change which allows smaller guilds and/or pickup groups access to...
content similar to what may have occurred in the 1999-2001 timeline due to emergency patches and downtimes.
It also brings us more in line with the quantity of raid targets which should have been spawned due to the aforementioned patches.. because we don't have multiple patches per month. Although the 2 simulated respawns per month worked in theory, late month occurrences led to players camping the timers. Starting in November, the simulated respawn system will work like this: 0-3 Simulated Respawns will occur each month; 1-3 being the normal amount, and 0 existing as a possibility if we cannot do them at all. I hope this change serves to keep the simulated respawn system alive and random while reducing the desire to camp the timers themselves. Enjoy!

Raiding

Raid mobs are more complex, and thus harder to classically re-create, than regular mobs. Exact details of their mechanics weren't always known, and on top of that players on Project 1999 had (literally) years more of Kunark than players on live, which means that they are generally more powerful. As a result, the dev team has had to walk a fine line: on the one hand they want things classic, but on the other they also don't want raid mobs to be too easy, and since they don't always know exactly what the classic mechanics were they sometimes get things wrong.

The following raid-related issues are known to be un-classic for one or more of the above reasons:

  • As mentioned above Project 1999 has simulated raid mob re-pops which are similar to, but not exactly the same, as the live servers coming down for patches on a semi-regular basis, creating raid respawns as a side effect.
  • Incorrect Resist Checks for Veeshan's Peak Dragon AEs - there is a bug filed for this issue, and the staff are aware of it (Sirken himself bumped the thread)
  • Sleeper's Tomb Warders - logs from live have shown that three of the warders, Ventani, Hraashna, and Tukaarak, (the fourth was left untouched on live to prevent the Sleeper from waking and thus has no logs) hit for the wrong amounts; a bug with evidence has been submitted but there has not yet been a dev response
  • Drop Rates - ToV dragons, PoM and PoH have been reported as deliberately having incorrect drop rates.
  • Veeshan's Peak "Dropables": Mask of Magma, Lava Drake Hide Sleeves[2]
  • High-level raid mobs have large variance (random component to their respawn time) on p1999, but were somewhat more predictable on Live.[3][4][5]
  • When raid mobs are engaged on Project 1999 the server sends out a "FTE (First to Engage) Message". This helps clarify which raid force first engaged the mob, and thus has the right to fight it, avoiding "kill stealing" issues. However this announcement did not occur on live.
    • On live guilds very rarely "raced" to a mob, and when they did the matter was either settled by DPS race (if no one petitioned) or by the live GM decision at the time.

Developer Fiat

Some, very rare, changes are made purely because the developer's felt it made the game so much better and/or was so minor overall that they deliberately chose to be nonclassic:

  • Ocean of Tears Boats
    • One change in the game that has no justification other than "the developers wanted it' are the Ocean of Tears boats. This change is the direction the boats travel: on Project 1999 the boats travel in the opposite direction. This change was made because the live version of Ocean of Tears had its original East-West axis switched. Since logically it makes no sense for boats from Freeport to travel West to get to Faydwer (and vice versa) the developers switched the directions in this zone.
  • Siren's Grotto Camp Bug Fix
  • Gnoll Fangs Quest Pre-Nerfed Green2019
    • With Green2019's launch Gnoll Fangs quest experience was Pre-nerfed. On live from classic to mid-kunark gnoll fangs quest granted substantially more experience per turn-in. On live in mid-kunark it was nerfed to give less experience per turn in, Green2019 launched with this nerf.
  • SoulFire Quest
    • Non Paladins who complete the SoulFire quest will receive a SoulFire with 0 charges. [6]
  • Clickie Recharging/Cast Time
    • Changed buyback price (and in one case removing the ability to sell the item to merchants), and adding cast times to some of the items. [7]
  • Quest Exp Disabled First Month of Kunark Green 2019
    • Disabled quest exp for the first month of kunark on the green 2019 server. Was done in response to players corpsing/muling quest items to turn in for fast exp on kunark launch. [8]
  • Nerfed Quest Experience
    • After the quest experience was re-added, 1 month into green2019 kunark, quest experience rewarded across the board was nerfed by as much as 50% for some quests.
  • Mouse Wheel Camera Zoom
    • Being able to zoom the camera in and out of first person and third person was not a feature of the older clients. Despite the developers having the knowledge and ability to Disable this they have chosen to keep it.
  • Teal Consider Color
    • P99's timeline extends to the end of velious when the teal consider color was first introduced (inside p99's timeline). Rogean has said there are no plans to re-implement the teal consider color on p99. Red/Blue/Green 1.0 should all have teal consider color as per the official live timeline.

Post-Luclin (Extremely Unlikely to be Implemented)

These are common user questions about things not seen in Project 1999 or seen differently from EverQuest Live that are intentionally so because they were introduced with or post-Luclin expansion. As such, these items will never match EverQuest Live on Project 1999.

Quests

  • Newbie armor quests:[9]
    • Kelethin Bard (Tranquilsong) Armor
    • Rivervale Druid (Moss Toe) Armor
    • etc.
  • Qeynos Badge of Nobility (4th)[10]

Epic Quests

The original epic ("1.0") quests were often changed later, and so guides you might find elsewhere will not be accurate to p99. This is a list noting the major differences between the classic epic quests and their revamped versions, where applicable.

Class Changes between Live and Classic Live
Cleric
Magician
Wizard

Zones

These zones are Luclin+ and will likely never be implemented on P99 Blue/Red except (possibly, someday) in a custom form (and never on Green)

Other Known, Non-Classic Changes

Game Mechanics

  • Summoned pets cannot dual wield without weapons, regardless of level.reference?
  • Restore full DoT damage to moving (non-feared) mobs occurred during Velious?reference?
  • NPCs would drop items they had been previously given on live, but not on p1999.reference?
  • You cannot drop coin on the ground - only items.
  • Bards cannot swarm (max 4 mobs hit by PBAoE).
  • Charming a mob and sending it into the Priest of Discord will no longer trigger an epic battle vs the guards of that city.
  • Combining mats in a kit that don't make something will not eat them.
  • Combining a stack of mats in a kit will popup a warning that you're doing it wrong.

Mobs/Drops

  • Manastone drop rate made significantly-more rare on Teal/Green.reference?

Quests

  • Tumpy Tonic exp quest nerfed (possibly non-existent?).

Spells

UI & Chat

  • /note exists.
  • /gems exists.
  • Item links exist.
  • Queued /tell's while zoning instead of showing offline.
  • Opaque "stone" UI is replaced with transparent version.
  • You cannot remove trades once it's on the trade screen.

Zone Geography

  • Not able to click firepot for Rogue Disarm Traps skill-up in Timorous Deep.reference?

Unconfirmed Changes

The following have been reported in the forums as unclassic, but they have not (as far as this author knows) been confirmed. If they are unclassic, no developer reason is known at this time.

(NOTE: This is a wiki, if the above is untrue and you have further information please feel free to update this page.)


  • NPC spellbooks
  • Lifetap resist checks due to Ivandyr's nerf
  • Sneak pulling mechanics
  • FD memblur mechanics
  • Bard spell stacking
  • ENC/CLR Memblur success rates
  • Most of the ring war mechanics
  • Raid mob AC
  • INT/WIS not obeying diminishing returns over 200
  • Raid-Related:
    • loot tables
    • dragon hp
    • dragon fear
    • DA agro mechanic
    • Rooted NToV dragons
    • NToV drop rates
    • Respawn variance

Red/PvP

  • At the beginning of Red, players would suffer exp loss on PvP death (arguably the #1 cause of Red's demise), despite no live PvP servers ever doing this.
  • Faster exp (0.5?) gain.
  • Global OOC came later when the population hit an average player count of ~50.
  • In the early days, a bard's Selo's used to break snare/root - but was not honored on Red.

Why Do We Still Have All This Unclassic Stuff After a Decade?

Especially when a long-standing unclassic feature is removed from Project 1999, many players wonder, why was that unclassic feature present for such a long time?

As it turns out, reverse engineering decades-old compiled computer source code is really, really difficult ...

Frankly this argument annoys me. You guys underestimate the difficulty of client side changes. We don't have access to Client source code. We have very limited dissassembly skillsets, and occasionally we rely on pseudocode. Haynar is better than I am at finding specific memory addresses and offsets, and I'm somewhat decent at finding/following code paths for functions to hook and modify their arguments and/or return values. Secrets is better than both of us at anything related to dissassembly, but often too busy to help us.

The Client psuedocode is 468,710 lines of code long, and most of it looks a lot like this:

//----- (0041ACE9) --------------------------------------------------------
signed int __thiscall sub_41ACE9(_DWORD *this, unsigned int a2)
{
  _DWORD *v2; // esi
  int v3; // edx
  int v4; // eax
  int v5; // edi
  signed int v6; // ebx
  int v7; // edi
  int v8; // eax
  int v9; // edi
  int v10; // eax
  int v11; // eax
  int v12; // eax
  int v13; // eax
  int v14; // edi
  char v15; // al
  int v16; // eax
  signed int v17; // ecx
  int v18; // eax
  int v19; // ebx
  signed int v20; // edi
  _DWORD *v21; // eax
  _DWORD *v22; // eax
  int v23; // eax
  int v24; // eax
  int v25; // edi
  int v26; // eax
  signed int v28; // [esp+Ch] [ebp-4h]
  _DWORD *v29; // [esp+Ch] [ebp-4h]

  v2 = this;
  v28 = sub_40E722((_DWORD *)((char *)this + *(_DWORD *)(this[1] + 4) + 4), a2);
  v4 = v2[2];
  if ( v4
    && !*(_BYTE *)(v4 + 580)
    && !*(_BYTE *)(v4 + 598)
    && !sub_4167E2((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 4)) )
  {
    v29 = (_DWORD *)(*(int (**)(void))(*(_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 4) + 64))();
    v5 = *(_DWORD *)(sub_5EC220((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 8)) + 4516);
    v6 = *(_DWORD *)(sub_5EC220((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 8)) + 4516);
    if ( v6 < (unsigned __int8)sub_5ED510(v29) )
    {
      v7 = *(_DWORD *)(sub_5EC220((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 8)) + 4516);
      if ( (unsigned __int8)sub_5ED510(v29) >= v7 + 2 )
        v5 = *(_DWORD *)(sub_5EC220((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 8)) + 4516) + 2;
      else
        v5 = (unsigned __int8)sub_5ED510(v29);
    }
    v8 = sub_5EC220((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 8));
    v9 = sub_44A448(v5, *(unsigned __int8 *)(v8 + 4508), a2, (int)v29);
    if ( sub_40E722((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 4), a2) < v9 )
      v9 = sub_40E722((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 4), a2);
    v10 = sub_5EC220((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 8));
    v11 = sub_4184F4(v2, a2, *(_DWORD *)(v10 + 4504));
    v28 = v9;
    if ( v9 <= v11 )
      v28 = v11;
  }
  v12 = v2[2];
  if ( v12 )
  {
    if ( !*(_BYTE *)(v12 + 580) )
    {
      v13 = sub_40E934((int)v2, v3, 122, 0);
      v14 = v13;
      if ( v13 )
      {
        sub_44D0D0(*(_DWORD *)(v13 + 4));
        if ( v15 )
        {
          sub_40CBD6(*(_DWORD *)(v14 + 4));
          if ( v16 )
          {
            if ( *(_DWORD *)(v16 + 48) == a2 )
            {
              v17 = *(_DWORD *)(v16 + 240);
              if ( v17 > 0 && v17 < 101 )
                v28 = v28 * (100 - v17) / 100;
            }
          }
        }
      }
    }
  }
  v18 = v2[2];
  v19 = 0;
  if ( v18 && !*(_BYTE *)(v18 + 580) )
  {
    v20 = 0;
    do
    {
      if ( sub_40CC50((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 4), v20) )
      {
        v21 = (_DWORD *)sub_40CC50((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 4), v20);
        if ( !sub_5ECCC0(v21) )
        {
          v22 = (_DWORD *)sub_40CC50((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 4), v20);
          v23 = sub_5E3210(v22, a2, v28, 1);
          if ( v23 )
          {
            if ( v23 > v19 )
              v19 = v23;
          }
        }
      }
      ++v20;
    }
    while ( v20 < 22 );
    if ( v19 )
      v28 += v19;
    if ( a2 == 35 )
    {
      if ( *(_DWORD *)(sub_5EC220((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 8)) + 136) )
      {
        v24 = sub_5EC220((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 8));
        v25 = sub_5E3210(*(_DWORD **)(v24 + 136), 35, v28, 1);
        v26 = sub_5EC220((_DWORD *)((char *)v2 + *(_DWORD *)(v2[1] + 4) + 8));
        if ( sub_5ECC00(*(_DWORD **)(v26 + 136)) == 12 )
        {
          if ( v25 )
            v28 += v25;
        }
      }
    }
  }
  if ( v28 > 252 && sub_44A273(a2) )
    v28 = 252;
  return v28;
}
// 40CBD6: using guessed type double __stdcall sub_40CBD6(_DWORD);
// 44D0D0: using guessed type double __cdecl sub_44D0D0(_DWORD);

Now, the function I just listed above is a good example, because it handles the client's visual display of the values of skills in the skill window. In this function, it's handling a lot of processing on those values to check various caps based on class and skill ID, which it really should have no reason to do because we just want it to display what the server tells us it is.

So, we hook it. Hooking is essentially rewriting the running code in memory at the location of this function to do a JMP (Jump/Detour) to our own custom function. At which point we access the Skill Value directly, using a global client pointer to the character's data, and return it:

signed int CHooks::SkillCapCheck2_Detour(unsigned int a1) { return ((CharData2 *)((*(CharData **)0x905D00)->ExtendedData->pCharData2))->Skill[a1]; }

And this is actually one of the easier examples.

See also