From d878c2e7d6a5288fa140d08a9adb036cab8d7eca Mon Sep 17 00:00:00 2001
From: Randy Heit <rheit@zdoom.fake>
Date: Wed, 10 May 2006 02:40:43 +0000
Subject: [PATCH] - Backported the classnames-are-names changes from the FP
 code.

SVN r97 (trunk)
---
 default.cbd                       | 360 ++++++++++++++++++++----
 docs/rh-log.txt                   |   1 +
 src/actor.h                       |  24 +-
 src/autostart.cpp                 |   2 +-
 src/b_think.cpp                   |   6 +-
 src/c_cmds.cpp                    |  13 +-
 src/ct_chat.cpp                   |   6 +-
 src/d_dehacked.cpp                |  48 ++--
 src/d_main.cpp                    |   2 +-
 src/d_net.cpp                     |   4 +-
 src/d_player.h                    |   6 +-
 src/decallib.cpp                  |  20 +-
 src/decallib.h                    |   4 +-
 src/decorations.cpp               |  47 ++--
 src/dobject.cpp                   | 439 ++++++++++--------------------
 src/dobject.h                     |  90 +++---
 src/dobjtype.cpp                  | 268 ++++++++++++++++++
 src/dobjtype.h                    |  60 ++++
 src/doomtype.h                    |   1 +
 src/dthinker.cpp                  |   4 +-
 src/dthinker.h                    |   6 +-
 src/f_finale.cpp                  |  14 +-
 src/farchive.cpp                  |  74 ++---
 src/farchive.h                    |  20 +-
 src/g_doom/a_doomartifacts.cpp    |   2 +-
 src/g_doom/a_doomglobal.h         |   2 +-
 src/g_doom/a_doomplayer.cpp       |   6 +-
 src/g_doom/a_doomweaps.cpp        |   4 +-
 src/g_doom/a_fatso.cpp            |  16 +-
 src/g_doom/a_keen.cpp             |   2 +-
 src/g_doom/a_painelemental.cpp    |   4 +-
 src/g_doom/a_scriptedmarine.cpp   |   4 +-
 src/g_doom/doom_sbar.cpp          |  14 +-
 src/g_game.cpp                    |  18 +-
 src/g_heretic/a_hereticplayer.cpp |   6 +-
 src/g_heretic/a_hereticweaps.cpp  |   6 +-
 src/g_heretic/heretic_sbar.cpp    |   2 +-
 src/g_hexen/a_centaur.cpp         |   2 +-
 src/g_hexen/a_clericholy.cpp      |   2 +-
 src/g_hexen/a_clericplayer.cpp    |   2 +-
 src/g_hexen/a_demons.cpp          |   8 +-
 src/g_hexen/a_fighteraxe.cpp      |   2 +-
 src/g_hexen/a_fighterplayer.cpp   |   4 +-
 src/g_hexen/a_fighterquietus.cpp  |   2 +-
 src/g_hexen/a_firedemon.cpp       |   2 +-
 src/g_hexen/a_flechette.cpp       |   2 +-
 src/g_hexen/a_fog.cpp             |   2 +-
 src/g_hexen/a_heresiarch.cpp      |   2 +-
 src/g_hexen/a_hexenglobal.h       |   4 +-
 src/g_hexen/a_iceguy.cpp          |   2 +-
 src/g_hexen/a_korax.cpp           |  12 +-
 src/g_hexen/a_mageplayer.cpp      |   2 +-
 src/g_hexen/a_magestaff.cpp       |   2 +-
 src/g_hexen/a_mana.cpp            |   6 +-
 src/g_hexen/a_serpent.cpp         |   2 +-
 src/g_hexen/a_teleportother.cpp   |   2 +-
 src/g_hexen/hexen_sbar.cpp        |   6 +-
 src/g_level.cpp                   |   2 +-
 src/g_level.h                     |   2 +-
 src/g_raven/a_artiegg.cpp         |  12 +-
 src/g_raven/a_minotaur.cpp        |   6 +-
 src/g_raven/ravenshared.h         |   2 +-
 src/g_shared/a_artifacts.h        |   2 +-
 src/g_shared/a_debris.cpp         |   4 +-
 src/g_shared/a_keys.cpp           |  19 +-
 src/g_shared/a_pickups.cpp        |  28 +-
 src/g_shared/a_pickups.h          |  24 +-
 src/g_shared/a_weaponpiece.cpp    |   2 +-
 src/g_shared/a_weaponpiece.h      |   2 +-
 src/g_shared/a_weapons.cpp        |  24 +-
 src/g_shared/sbar.h               |   2 +-
 src/g_shared/shared_sbar.cpp      |   2 +-
 src/g_strife/a_alienspectres.cpp  |   4 +-
 src/g_strife/a_strifeglobal.h     |   2 +-
 src/g_strife/a_strifeplayer.cpp   |   2 +-
 src/g_strife/a_strifestuff.cpp    |   2 +-
 src/g_strife/a_strifeweapons.cpp  |   8 +-
 src/g_strife/a_thingstoblowup.cpp |   2 +-
 src/g_strife/strife_sbar.cpp      |  22 +-
 src/info.cpp                      |  44 ++-
 src/info.h                        |  13 +-
 src/infodefaults.cpp              |  34 +--
 src/infomacros.h                  |   4 +-
 src/m_cheat.cpp                   |  46 ++--
 src/m_menu.cpp                    |  12 +-
 src/name.cpp                      |   6 +-
 src/name.h                        |   4 +-
 src/namedef.h                     |  48 +++-
 src/p_acs.cpp                     |  42 +--
 src/p_conversation.cpp            |  20 +-
 src/p_conversation.h              |  12 +-
 src/p_enemy.cpp                   |  35 +--
 src/p_enemy.h                     |   4 +-
 src/p_interaction.cpp             |   8 +-
 src/p_lnspec.cpp                  |   2 +-
 src/p_local.h                     |  30 +-
 src/p_map.cpp                     |   4 +-
 src/p_maputl.cpp                  |   2 +-
 src/p_mobj.cpp                    |  77 +++---
 src/p_pspr.cpp                    |   2 +-
 src/p_pspr.h                      |   2 +-
 src/p_terrain.cpp                 |   6 +-
 src/p_terrain.h                   |   6 +-
 src/p_things.cpp                  |   8 +-
 src/p_user.cpp                    |   8 +-
 src/thingdef.cpp                  | 162 ++++++-----
 src/thingdef_codeptr.cpp          |  36 +--
 zdoom.vcproj                      |   6 +
 108 files changed, 1477 insertions(+), 1054 deletions(-)
 create mode 100644 src/dobjtype.cpp
 create mode 100644 src/dobjtype.h

diff --git a/default.cbd b/default.cbd
index 45ef935a3..c8b17296a 100644
--- a/default.cbd
+++ b/default.cbd
@@ -136,67 +136,307 @@ else
 
 done
 
-${COMPILER} "autostart.cpp a.nas blocks.nas misc.nas tmap.nas tmap2.nas tmap3.nas \
- am_map.cpp b_bot.cpp b_func.cpp b_game.cpp b_move.cpp b_think.cpp bbannouncer.cpp \
- c_bind.cpp c_cmds.cpp c_console.cpp c_cvars.cpp c_dispatch.cpp c_expr.cpp \
- cmdlib.cpp colormatcher.cpp configfile.cpp ct_chat.cpp d_dehacked.cpp d_main.cpp \
- d_net.cpp d_netinfo.cpp d_protocol.cpp decallib.cpp decorations.cpp dobject.cpp \
- doomdef.cpp doomstat.cpp dsectoreffect.cpp dthinker.cpp empty.cpp f_finale.cpp \
- f_wipe.cpp farchive.cpp files.cpp g_game.cpp g_hub.cpp g_level.cpp gameconfigfile.cpp \ 
- gi.cpp hu_scores.cpp info.cpp infodefaults.cpp lumpconfigfile.cpp m_alloc.cpp \
- m_argv.cpp m_bbox.cpp m_cheat.cpp m_fixed.cpp m_menu.cpp m_misc.cpp m_options.cpp \
- m_png.cpp m_random.cpp mus2midi.cpp nodebuild.cpp nodebuild_events.cpp \
- nodebuild_extract.cpp nodebuild_gl.cpp nodebuild_utility.cpp p_acs.cpp \
- p_buildmap.cpp p_ceiling.cpp p_conversation.cpp p_doors.cpp p_effect.cpp \
- p_enemy.cpp p_floor.cpp p_interaction.cpp p_lights.cpp p_lnspec.cpp p_map.cpp \
- p_maputl.cpp p_mobj.cpp p_pillar.cpp p_plats.cpp p_pspr.cpp p_saveg.cpp \
- p_sectors.cpp p_setup.cpp p_sight.cpp p_spec.cpp p_switch.cpp p_teleport.cpp \
- p_terrain.cpp p_things.cpp p_tick.cpp p_trace.cpp p_user.cpp p_writemap.cpp \
- p_xlat.cpp po_man.cpp r_bsp.cpp r_data.cpp r_draw.cpp r_drawt.cpp r_main.cpp \
- r_plane.cpp r_segs.cpp r_sky.cpp r_things.cpp r_polymost.cpp s_advsound.cpp \
- s_environment.cpp s_playlist.cpp s_sndseq.cpp s_sound.cpp sc_man.cpp skins.cpp \
- st_stuff.cpp stats.cpp stringtable.cpp tables.cpp tempfiles.cpp thingdef.cpp thingdef_codeptr.cpp thingdef_exp.cpp \
- v_collection.cpp v_draw.cpp v_font.cpp v_palette.cpp v_pfx.cpp v_text.cpp \
- v_video.cpp vectors.cpp name.cpp zstring.cpp zstringpool.cpp zstrformat.cpp \
- w_wad.cpp wi_stuff.cpp a_arachnotron.cpp a_archvile.cpp a_bossbrain.cpp \
- a_bruiser.cpp a_cacodemon.cpp a_cyberdemon.cpp a_demon.cpp \
- a_doomartifacts.cpp a_doomhealth.cpp \
- a_doomimp.cpp a_doommisc.cpp a_doomplayer.cpp a_doomweaps.cpp \
- a_fatso.cpp a_keen.cpp a_lostsoul.cpp a_painelemental.cpp a_possessed.cpp \
- a_revenant.cpp a_scriptedmarine.cpp a_spidermaster.cpp doom_sbar.cpp a_beast.cpp \
- a_chicken.cpp a_clink.cpp a_dsparil.cpp \
- a_hereticartifacts.cpp a_hereticimp.cpp a_heretickeys.cpp \
- a_hereticmisc.cpp a_hereticplayer.cpp a_hereticweaps.cpp a_ironlich.cpp \
- a_knight.cpp a_mummy.cpp a_snake.cpp a_wizard.cpp heretic_sbar.cpp a_bats.cpp \
- a_bishop.cpp a_blastradius.cpp a_boostarmor.cpp a_centaur.cpp a_clericboss.cpp \
- a_clericflame.cpp a_clericholy.cpp a_clericmace.cpp a_clericplayer.cpp \
- a_clericstaff.cpp a_demons.cpp a_dragon.cpp a_ettin.cpp a_fighteraxe.cpp \
- a_fighterboss.cpp a_fighterhammer.cpp a_fighterplayer.cpp a_fighterquietus.cpp \
- a_firedemon.cpp a_flechette.cpp a_fog.cpp a_healingradius.cpp \
+${COMPILER} "autostart.cpp \
+ a.nas \
+ blocks.nas \
+ misc.nas \
+ tmap.nas \
+ tmap2.nas \
+ tmap3.nas \
+ am_map.cpp \
+ b_bot.cpp \
+ b_func.cpp \
+ b_game.cpp \
+ b_move.cpp \
+ b_think.cpp \
+ bbannouncer.cpp \
+ c_bind.cpp \
+ c_cmds.cpp \
+ c_console.cpp \
+ c_cvars.cpp \
+ c_dispatch.cpp \
+ c_expr.cpp \
+ cmdlib.cpp \
+ colormatcher.cpp \
+ configfile.cpp \
+ ct_chat.cpp \
+ d_dehacked.cpp \
+ d_main.cpp \
+ d_net.cpp \
+ d_netinfo.cpp \
+ d_protocol.cpp \
+ decallib.cpp \
+ decorations.cpp \
+ dobject.cpp \
+ dobjtype.cpp \
+ doomdef.cpp \
+ doomstat.cpp \
+ dsectoreffect.cpp \
+ dthinker.cpp \
+ empty.cpp \
+ f_finale.cpp \
+ f_wipe.cpp \
+ farchive.cpp \
+ files.cpp \
+ g_game.cpp \
+ g_hub.cpp \
+ g_level.cpp \
+ gameconfigfile.cpp \
+ gi.cpp \
+ hu_scores.cpp \
+ info.cpp \
+ infodefaults.cpp \
+ lumpconfigfile.cpp \
+ m_alloc.cpp \
+ m_argv.cpp \
+ m_bbox.cpp \
+ m_cheat.cpp \
+ m_fixed.cpp \
+ m_menu.cpp \
+ m_misc.cpp \
+ m_options.cpp \
+ m_png.cpp \
+ m_random.cpp \
+ mus2midi.cpp \
+ nodebuild.cpp \
+ nodebuild_events.cpp \
+ nodebuild_extract.cpp \
+ nodebuild_gl.cpp \
+ nodebuild_utility.cpp \
+ p_acs.cpp \
+ p_buildmap.cpp \
+ p_ceiling.cpp \
+ p_conversation.cpp \
+ p_doors.cpp \
+ p_effect.cpp \
+ p_enemy.cpp \
+ p_floor.cpp \
+ p_interaction.cpp \
+ p_lights.cpp \
+ p_lnspec.cpp \
+ p_map.cpp \
+ p_maputl.cpp \
+ p_mobj.cpp \
+ p_pillar.cpp \
+ p_plats.cpp \
+ p_pspr.cpp \
+ p_saveg.cpp \
+ p_sectors.cpp \
+ p_setup.cpp \
+ p_sight.cpp \
+ p_spec.cpp \
+ p_switch.cpp \
+ p_teleport.cpp \
+ p_terrain.cpp \
+ p_things.cpp \
+ p_tick.cpp \
+ p_trace.cpp \
+ p_user.cpp \
+ p_writemap.cpp \
+ p_xlat.cpp \
+ po_man.cpp \
+ r_bsp.cpp \
+ r_data.cpp \
+ r_draw.cpp \
+ r_drawt.cpp \
+ r_main.cpp \
+ r_plane.cpp \
+ r_segs.cpp \
+ r_sky.cpp \
+ r_things.cpp \
+ r_polymost.cpp \
+ s_advsound.cpp \
+ s_environment.cpp \
+ s_playlist.cpp \
+ s_sndseq.cpp \
+ s_sound.cpp \
+ sc_man.cpp \
+ skins.cpp \
+ st_stuff.cpp \
+ stats.cpp \
+ stringtable.cpp \
+ tables.cpp \
+ tempfiles.cpp \
+ thingdef.cpp \
+ thingdef_codeptr.cpp \
+ thingdef_exp.cpp \
+ v_collection.cpp \
+ v_draw.cpp \
+ v_font.cpp \
+ v_palette.cpp \
+ v_pfx.cpp \
+ v_text.cpp \
+ v_video.cpp \
+ vectors.cpp \
+ name.cpp \
+ zstring.cpp \
+ zstringpool.cpp \
+ zstrformat.cpp \
+ w_wad.cpp \
+ wi_stuff.cpp \
+ a_arachnotron.cpp \
+ a_archvile.cpp \
+ a_bossbrain.cpp \
+ a_bruiser.cpp \
+ a_cacodemon.cpp \
+ a_cyberdemon.cpp \
+ a_demon.cpp \
+ a_doomartifacts.cpp \
+ a_doomhealth.cpp \
+ a_doomimp.cpp \
+ a_doommisc.cpp \
+ a_doomplayer.cpp \
+ a_doomweaps.cpp \
+ a_fatso.cpp \
+ a_keen.cpp \
+ a_lostsoul.cpp \
+ a_painelemental.cpp \
+ a_possessed.cpp \
+ a_revenant.cpp \
+ a_scriptedmarine.cpp \
+ a_spidermaster.cpp \
+ doom_sbar.cpp \
+ a_beast.cpp \
+ a_chicken.cpp \
+ a_clink.cpp \
+ a_dsparil.cpp \
+ a_hereticartifacts.cpp \
+ a_hereticimp.cpp \
+ a_heretickeys.cpp \
+ a_hereticmisc.cpp \
+ a_hereticplayer.cpp \
+ a_hereticweaps.cpp \
+ a_ironlich.cpp \
+ a_knight.cpp \
+ a_mummy.cpp \
+ a_snake.cpp \
+ a_wizard.cpp \
+ heretic_sbar.cpp \
+ a_bats.cpp \
+ a_bishop.cpp \
+ a_blastradius.cpp \
+ a_boostarmor.cpp \
+ a_centaur.cpp \
+ a_clericboss.cpp \
+ a_clericflame.cpp \
+ a_clericholy.cpp \
+ a_clericmace.cpp \
+ a_clericplayer.cpp \
+ a_clericstaff.cpp \
+ a_demons.cpp \
+ a_dragon.cpp \
+ a_ettin.cpp \
+ a_fighteraxe.cpp \
+ a_fighterboss.cpp \
+ a_fighterhammer.cpp \
+ a_fighterplayer.cpp \
+ a_fighterquietus.cpp \
+ a_firedemon.cpp \
+ a_flechette.cpp \
+ a_fog.cpp \
+ a_healingradius.cpp \
  a_heresiarch.cpp \
- a_hexenspecialdecs.cpp a_iceguy.cpp a_korax.cpp a_mageboss.cpp a_magecone.cpp \
- a_magelightning.cpp a_mageplayer.cpp a_magestaff.cpp a_magewand.cpp a_mana.cpp \
- a_pig.cpp a_puzzleitems.cpp a_serpent.cpp \
- a_spike.cpp a_summon.cpp a_teleportother.cpp a_weaponpieces.cpp a_wraith.cpp \
- hexen_sbar.cpp a_artiegg.cpp a_artitele.cpp a_minotaur.cpp a_ravenambient.cpp \
- a_acolyte.cpp a_alienspectres.cpp \
- a_coin.cpp a_crusader.cpp a_entityboss.cpp a_inquisitor.cpp \
- a_loremaster.cpp a_macil.cpp a_oracle.cpp \
- a_programmer.cpp a_reaver.cpp a_rebels.cpp \
- a_sentinel.cpp a_spectral.cpp a_stalker.cpp a_strifeammo.cpp \
- a_strifebishop.cpp a_strifeitems.cpp a_strifeplayer.cpp \
- a_strifestuff.cpp a_strifeweapons.cpp a_templar.cpp a_thingstoblowup.cpp \
- strife_sbar.cpp a_action.cpp a_artifacts.cpp a_bridge.cpp \
- a_camera.cpp a_debris.cpp a_decals.cpp a_flashfader.cpp a_fountain.cpp \
- a_hatetarget.cpp a_keys.cpp a_lightning.cpp a_movingcamera.cpp a_pickups.cpp \
- a_quake.cpp a_secrettrigger.cpp a_sectoraction.cpp a_sharedmisc.cpp a_skies.cpp \
- a_soundenvironment.cpp a_soundsequence.cpp a_spark.cpp a_waterzone.cpp a_weaponpiece.cpp a_weapons.cpp \
- hudmessages.cpp shared_sbar.cpp fmopl.cpp mlkernel.cpp mlopl.cpp mlopl_io.cpp \
- opl_mus_player.cpp fmodsound.cpp i_music.cpp i_sound.cpp music_cd.cpp \
- music_flac.cpp music_midi_midiout.cpp music_midi_stream.cpp music_midi_timidity.cpp \
- music_mod.cpp music_mus_midiout.cpp music_mus_opl.cpp music_stream.cpp \
- sample_flac.cpp crashcatcher.c i_input.cpp i_net.cpp i_cd.cpp i_main.cpp \
- i_system.cpp hardware.cpp i_movie.cpp sdlvideo.cpp autozend.cpp"
+ a_hexenspecialdecs.cpp \
+ a_iceguy.cpp \
+ a_korax.cpp \
+ a_mageboss.cpp \
+ a_magecone.cpp \
+ a_magelightning.cpp \
+ a_mageplayer.cpp \
+ a_magestaff.cpp \
+ a_magewand.cpp \
+ a_mana.cpp \
+ a_pig.cpp \
+ a_puzzleitems.cpp \
+ a_serpent.cpp \
+ a_spike.cpp \
+ a_summon.cpp \
+ a_teleportother.cpp \
+ a_weaponpieces.cpp \
+ a_wraith.cpp \
+ hexen_sbar.cpp \
+ a_artiegg.cpp \
+ a_artitele.cpp \
+ a_minotaur.cpp \
+ a_ravenambient.cpp \
+ a_acolyte.cpp \
+ a_alienspectres.cpp \
+ a_coin.cpp \
+ a_crusader.cpp \
+ a_entityboss.cpp \
+ a_inquisitor.cpp \
+ a_loremaster.cpp \
+ a_macil.cpp \
+ a_oracle.cpp \
+ a_programmer.cpp \
+ a_reaver.cpp \
+ a_rebels.cpp \
+ a_sentinel.cpp \
+ a_spectral.cpp \
+ a_stalker.cpp \
+ a_strifeammo.cpp \
+ a_strifebishop.cpp \
+ a_strifeitems.cpp \
+ a_strifeplayer.cpp \
+ a_strifestuff.cpp \
+ a_strifeweapons.cpp \
+ a_templar.cpp \
+ a_thingstoblowup.cpp \
+ strife_sbar.cpp \
+ a_action.cpp \
+ a_artifacts.cpp \
+ a_bridge.cpp \
+ a_camera.cpp \
+ a_debris.cpp \
+ a_decals.cpp \
+ a_flashfader.cpp \
+ a_fountain.cpp \
+ a_hatetarget.cpp \
+ a_keys.cpp \
+ a_lightning.cpp \
+ a_movingcamera.cpp \
+ a_pickups.cpp \
+ a_quake.cpp \
+ a_secrettrigger.cpp \
+ a_sectoraction.cpp \
+ a_sharedmisc.cpp \
+ a_skies.cpp \
+ a_soundenvironment.cpp \
+ a_soundsequence.cpp \
+ a_spark.cpp \
+ a_waterzone.cpp \
+ a_weaponpiece.cpp \
+ a_weapons.cpp \
+ hudmessages.cpp \
+ shared_sbar.cpp \
+ fmopl.cpp \
+ mlkernel.cpp \
+ mlopl.cpp \
+ mlopl_io.cpp \
+ opl_mus_player.cpp \
+ fmodsound.cpp \
+ i_music.cpp \
+ i_sound.cpp \
+ music_cd.cpp \
+ music_flac.cpp \
+ music_midi_midiout.cpp \
+ music_midi_stream.cpp \
+ music_midi_timidity.cpp \
+ music_mod.cpp \
+ music_mus_midiout.cpp \
+ music_mus_opl.cpp \
+ music_stream.cpp \
+ sample_flac.cpp \
+ crashcatcher.c \
+ i_input.cpp \
+ i_net.cpp \
+ i_cd.cpp \
+ i_main.cpp \
+ i_system.cpp \
+ hardware.cpp \
+ i_movie.cpp \
+ sdlvideo.cpp \
+ autozend.cpp"
 
 ${LINK} "${TARGET}"
 
diff --git a/docs/rh-log.txt b/docs/rh-log.txt
index 4d3854c63..5182719ae 100644
--- a/docs/rh-log.txt
+++ b/docs/rh-log.txt
@@ -1,4 +1,5 @@
 May 9, 2006
+- Backported the classnames-are-names changes from the FP code.
 - Backported the improved hierarchical dumpclasses command from the FP code.
 - Updated Jim's Makefile.linux.
 - Added support for wrapping midtextures vertically.
diff --git a/src/actor.h b/src/actor.h
index f8b99e1aa..88b01b1e1 100644
--- a/src/actor.h
+++ b/src/actor.h
@@ -370,18 +370,18 @@ class AInventory;
 
 inline AActor *GetDefaultByName (const char *name)
 {
-	return (AActor *)(TypeInfo::FindType (name)->ActorInfo->Defaults);
+	return (AActor *)(PClass::FindClass(name)->Defaults);
 }
 
-inline AActor *GetDefaultByType (const TypeInfo *type)
+inline AActor *GetDefaultByType (const PClass *type)
 {
-	return (AActor *)(type->ActorInfo->Defaults);
+	return (AActor *)(type->Defaults);
 }
 
 template<class T>
 inline T *GetDefault ()
 {
-	return (T *)(RUNTIME_CLASS(T)->ActorInfo->Defaults);
+	return (T *)(RUNTIME_CLASS(T)->Defaults);
 }
 
 struct secplane_t;
@@ -417,11 +417,11 @@ public:
 
 	void Serialize (FArchive &arc);
 
-	static AActor *StaticSpawn (const TypeInfo *type, fixed_t x, fixed_t y, fixed_t z);
+	static AActor *StaticSpawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z);
 
 	inline AActor *GetDefault () const
 	{
-		return (AActor *)(RUNTIME_TYPE(this)->ActorInfo->Defaults);
+		return (AActor *)(RUNTIME_TYPE(this)->Defaults);
 	}
 
 	// BeginPlay: Called just after the actor is created
@@ -533,20 +533,20 @@ public:
 	bool CheckLocalView (int playernum) const;
 
 	// Finds the first item of a particular type.
-	AInventory *FindInventory (const TypeInfo *type) const;
+	AInventory *FindInventory (const PClass *type) const;
 	template<class T> T *FindInventory () const
 	{
 		return static_cast<T *> (FindInventory (RUNTIME_CLASS(T)));
 	}
 
 	// Adds one item of a particular type. Returns NULL if it could not be added.
-	AInventory *GiveInventoryType (const TypeInfo *type);
+	AInventory *GiveInventoryType (const PClass *type);
 
 	// Returns the first item held with IF_INVBAR set.
 	AInventory *FirstInv () const;
 
 	// Tries to give the actor some ammo.
-	bool GiveAmmo (const TypeInfo *type, int amount);
+	bool GiveAmmo (const PClass *type, int amount);
 
 	// Set the alphacolor field properly
 	void SetShade (DWORD rgb);
@@ -574,7 +574,7 @@ public:
 	bool IsHostile (AActor *other);
 
 	// What species am I?
-	virtual const TypeInfo *GetSpecies();
+	virtual const PClass *GetSpecies();
 	
 	// Check for monsters that count as kill but excludes all friendlies.
 	bool CountsAsKill() const
@@ -786,14 +786,14 @@ public:
 	}
 };
 
-inline AActor *Spawn (const TypeInfo *type, fixed_t x, fixed_t y, fixed_t z)
+inline AActor *Spawn (const PClass *type, fixed_t x, fixed_t y, fixed_t z)
 {
 	return AActor::StaticSpawn (type, x, y, z);
 }
 
 inline AActor *Spawn (const char *type, fixed_t x, fixed_t y, fixed_t z)
 {
-	return AActor::StaticSpawn (TypeInfo::FindType (type), x, y, z);
+	return AActor::StaticSpawn (PClass::FindClass(type), x, y, z);
 }
 
 template<class T>
diff --git a/src/autostart.cpp b/src/autostart.cpp
index e92f42900..c8690fc57 100644
--- a/src/autostart.cpp
+++ b/src/autostart.cpp
@@ -37,7 +37,7 @@
 ** that way can require a lot of extra space, which is why I'm doing things
 ** this way.
 **
-** In the case of TypeInfo lists (section creg), I orginally used the
+** In the case of PClass lists (section creg), I orginally used the
 ** constructor to do just that, and the code for that still exists if you
 ** compile with something other than Visual C++ or GCC.
 */
diff --git a/src/b_think.cpp b/src/b_think.cpp
index a43606fc9..6c3165869 100644
--- a/src/b_think.cpp
+++ b/src/b_think.cpp
@@ -123,7 +123,7 @@ void DCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd)
 		//Check if it's more important to get an item than fight.
 		if (b->dest && (b->dest->flags&MF_SPECIAL)) //Must be an item, that is close enough.
 		{
-#define is(x) b->dest->IsKindOf (TypeInfo::FindType (#x))
+#define is(x) b->dest->IsKindOf (PClass::FindClass (#x))
 			if (
 				(
 				 (actor->health < b->skill.isp &&
@@ -321,7 +321,7 @@ void DCajunMaster::WhatToGet (AActor *actor, AActor *item)
 		return;
 	}
 
-#define typeis(x) item->IsKindOf (TypeInfo::FindType (#x))
+#define typeis(x) item->IsKindOf (PClass::FindClass (#x))
 	if ((item->renderflags & RF_INVISIBLE) //Under respawn and away.
 		|| item == b->prev)
 	{
@@ -353,7 +353,7 @@ void DCajunMaster::WhatToGet (AActor *actor, AActor *item)
 	else if (item->IsKindOf (RUNTIME_CLASS(AAmmo)))
 	{
 		AAmmo *ammo = static_cast<AAmmo *> (item);
-		const TypeInfo *parent = ammo->GetParentAmmo ();
+		const PClass *parent = ammo->GetParentAmmo ();
 		AInventory *holdingammo = b->mo->FindInventory (parent);
 
 		if (holdingammo != NULL && holdingammo->Amount >= holdingammo->MaxAmount)
diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp
index b523d9b2d..6194f5919 100644
--- a/src/c_cmds.cpp
+++ b/src/c_cmds.cpp
@@ -713,7 +713,10 @@ CCMD(linetarget)
 	P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->angle,MISSILERANGE, 0);
 	if (linetarget)
 	{
-		Printf("Target=%s, Health=%d, Spawnhealth=%d\n",linetarget->GetClass()->Name+1,linetarget->health,linetarget->GetDefault()->health);
+		Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
+			linetarget->GetClass()->TypeName.GetChars(),
+			linetarget->health,
+			linetarget->GetDefault()->health);
 	}
 	else Printf("No target found\n");
 }
@@ -734,7 +737,9 @@ CCMD(monster)
 	{
 		if (mo->flags3&MF3_ISMONSTER && !(mo->flags&MF_CORPSE) && !(mo->flags&MF_FRIENDLY))
 		{
-			Printf ("%s at (%ld,%ld,%ld)\n", mo->GetClass()->Name+1, mo->x>>16, mo->y>>16, mo->z>>16);
+			Printf ("%s at (%ld,%ld,%ld)\n",
+				mo->GetClass()->TypeName.GetChars(),
+				mo->x >> FRACBITS, mo->y >> FRACBITS, mo->z >> FRACBITS);
 		}
 	}
 }
@@ -755,7 +760,9 @@ CCMD(items)
 	{
 		if (mo->IsKindOf(RUNTIME_CLASS(AInventory)) && mo->flags&MF_SPECIAL)
 		{
-			Printf ("%s at (%ld,%ld,%ld)\n",mo->GetClass()->Name+1,mo->x>>16,mo->y>>16,mo->z>>16);
+			Printf ("%s at (%ld,%ld,%ld)\n",
+				mo->GetClass()->TypeName.GetChars(),
+				mo->x >> FRACBITS, mo->y >> FRACBITS, mo->z >> FRACBITS);
 		}
 	}
 }
diff --git a/src/ct_chat.cpp b/src/ct_chat.cpp
index 4ad01a65d..9097ba23d 100644
--- a/src/ct_chat.cpp
+++ b/src/ct_chat.cpp
@@ -371,7 +371,7 @@ static bool DoSubstitution (char *out, const char *in)
 				}
 				else
 				{
-					out += sprintf (out, "%s", weapon->GetClass()->Name+1);
+					out += sprintf (out, "%s", weapon->GetClass()->TypeName.GetChars());
 				}
 			}
 		}
@@ -412,10 +412,10 @@ static bool DoSubstitution (char *out, const char *in)
 				}
 				else
 				{
-					out += sprintf (out, "%s", weapon->Ammo1->GetClass()->Name+1);
+					out += sprintf (out, "%s", weapon->Ammo1->GetClass()->TypeName.GetChars());
 					if (weapon->Ammo2 != NULL)
 					{
-						out += sprintf (out, "/%s", weapon->Ammo2->GetClass()->Name+1);
+						out += sprintf (out, "/%s", weapon->Ammo2->GetClass()->TypeName.GetChars());
 					}
 				}
 			}
diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp
index cccdf5d8c..da341e122 100644
--- a/src/d_dehacked.cpp
+++ b/src/d_dehacked.cpp
@@ -169,7 +169,7 @@ public:
 	void PlayPickupSound (AActor *toucher);
 	void DoPickupSpecial (AActor *toucher);
 private:
-	const TypeInfo *DetermineType ();
+	const PClass *DetermineType ();
 	AInventory *RealPickup;
 };
 
@@ -186,8 +186,8 @@ FState ADehackedPickup::States[] =
 BEGIN_DEFAULTS (ADehackedPickup, Any, -1, 0)
 END_DEFAULTS
 
-TArray<TypeInfo *> DehackedPickups;
-TArray<TypeInfo *> TouchedActors;
+TArray<PClass *> DehackedPickups;
+TArray<PClass *> TouchedActors;
 
 char *UnchangedSpriteNames;
 int NumUnchangedSprites;
@@ -299,7 +299,7 @@ struct StateMapper
 {
 	FState *State;
 	int StateSpan;
-	const TypeInfo *Owner;
+	const PClass *Owner;
 	bool OwnerIsPickup;
 };
 
@@ -477,7 +477,7 @@ static FState *FindState (int statenum)
 		{
 			if (StateMap[i].OwnerIsPickup)
 			{
-				TouchedActors.Push (const_cast<TypeInfo *>(StateMap[i].Owner));
+				TouchedActors.Push (const_cast<PClass *>(StateMap[i].Owner));
 			}
 			return StateMap[i].State + statenum - stateacc;
 		}
@@ -713,7 +713,7 @@ static int PatchThing (int thingy)
 	bool hadTranslucency = false;
 	bool hadStyle = false;
 	int oldflags;
-	const TypeInfo *type;
+	const PClass *type;
 	SWORD *ednum, dummyed;
 
 	type = NULL;
@@ -728,7 +728,7 @@ static int PatchThing (int thingy)
 		DPrintf ("Thing %d\n", thingy);
 		if (thingy > 0)
 		{
-			type = TypeInfo::FindType (GetName (InfoNames[thingy - 1]));
+			type = PClass::FindClass (GetName (InfoNames[thingy - 1]));
 			if (type == NULL)
 			{
 				info = &dummy;
@@ -1052,7 +1052,7 @@ static int PatchThing (int thingy)
 
 		if (info->flags & MF_SPECIAL)
 		{
-			TouchedActors.Push (const_cast<TypeInfo *>(type));
+			TouchedActors.Push (const_cast<PClass *>(type));
 		}
 
 		// Make MF3_ISMONSTER match MF_COUNTKILL
@@ -1293,7 +1293,7 @@ static int PatchSprite (int sprNum)
 
 static int PatchAmmo (int ammoNum)
 {
-	const TypeInfo *ammoType;
+	const PClass *ammoType;
 	AAmmo *defaultAmmo;
 	int result;
 	int *max;
@@ -1304,7 +1304,7 @@ static int PatchAmmo (int ammoNum)
 	if (ammoNum >= 0 && ammoNum < 4)
 	{
 		DPrintf ("Ammo %d.\n", ammoNum);
-		ammoType = TypeInfo::FindType (AmmoNames[ammoNum]);
+		ammoType = PClass::FindClass (AmmoNames[ammoNum]);
 		defaultAmmo = (AAmmo *)GetDefaultByType (ammoType);
 		max = &defaultAmmo->MaxAmount;
 		per = &defaultAmmo->Amount;
@@ -1336,9 +1336,9 @@ static int PatchAmmo (int ammoNum)
 	// Fix per-ammo/max-ammo amounts for descendants of the base ammo class
 	if (oldclip != *per)
 	{
-		for (int i = 0; i < TypeInfo::m_Types.Size(); ++i)
+		for (int i = 0; i < PClass::m_Types.Size(); ++i)
 		{
-			TypeInfo *type = TypeInfo::m_Types[i];
+			PClass *type = PClass::m_Types[i];
 
 			if (type == ammoType)
 				continue;
@@ -1411,7 +1411,7 @@ static int PatchWeapon (int weapNum)
 				{
 					val = 5;
 				}
-				info->AmmoType1 = TypeInfo::FindType (AmmoNames[val]);
+				info->AmmoType1 = PClass::FindClass (AmmoNames[val]);
 				if (info->AmmoType1 != NULL)
 				{
 					info->AmmoGive1 = ((AAmmo*)GetDefaultByType (info->AmmoType1))->Amount * 2;
@@ -1574,7 +1574,7 @@ static int PatchMisc (int dummy)
 					"Minotaur",
 					NULL
 				};
-				static const TypeInfo * const types[] =
+				static const PClass * const types[] =
 				{
 					RUNTIME_CLASS(APowerInvulnerable),
 					RUNTIME_CLASS(APowerStrength),
@@ -2431,7 +2431,7 @@ static bool LoadDehSupp ()
 				for (i = 0; i < NumStateMaps; i++)
 				{
 					const char *name = GetName (GetWord (supp + 6 + i*4));
-					const TypeInfo *type = TypeInfo::FindType (name);
+					const PClass *type = PClass::FindClass (name);
 					if (type == NULL)
 					{
 						Printf ("Can't find type %s\n", name);
@@ -2520,7 +2520,7 @@ void FinishDehPatch ()
 
 	for (touchedIndex = 0; touchedIndex < TouchedActors.Size(); ++touchedIndex)
 	{
-		TypeInfo *type = TouchedActors[touchedIndex];
+		PClass *type = TouchedActors[touchedIndex];
 		AActor *defaults1 = GetDefaultByType (type);
 		if (!(defaults1->flags & MF_SPECIAL))
 		{ // We only need to do this for pickups
@@ -2529,8 +2529,8 @@ void FinishDehPatch ()
 
 		// Create a new class that will serve as the actual pickup
 		char typeNameBuilder[32];
-		sprintf (typeNameBuilder, "ADehackedPickup%d", touchedIndex);
-		TypeInfo *subclass = RUNTIME_CLASS(ADehackedPickup)->CreateDerivedClass
+		sprintf (typeNameBuilder, "DehackedPickup%d", touchedIndex);
+		PClass *subclass = RUNTIME_CLASS(ADehackedPickup)->CreateDerivedClass
 			(copystring(typeNameBuilder), sizeof(ADehackedPickup));
 		AActor *defaults2 = GetDefaultByType (subclass);
 		memcpy (defaults2, defaults1, sizeof(AActor));
@@ -2548,7 +2548,7 @@ void FinishDehPatch ()
 		type->ActorInfo->SpawnID = 0;
 		type->ActorInfo->DoomEdNum = -1;
 
-		DPrintf ("%s replaces %s\n", subclass->Name, type->Name);
+		DPrintf ("%s replaces %s\n", subclass->TypeName.GetChars(), type->TypeName.GetChars());
 	}
 
 	// Since deh.MaxHealth was used incorrectly this can only be set
@@ -2565,7 +2565,7 @@ void HandleNoSector()
 
 	for (touchedIndex = 0; touchedIndex < TouchedActors.Size(); ++touchedIndex)
 	{
-		TypeInfo *ti = TouchedActors[touchedIndex];
+		PClass *ti = TouchedActors[touchedIndex];
 
 		if (ti!=NULL && ti->ActorInfo!=NULL && !ti->IsDescendantOf(RUNTIME_CLASS(ATeleportDest)))
 		{
@@ -2580,7 +2580,7 @@ void HandleNoSector()
 	}
 	// The BossEye must be handled even without any Dehacked interference
 	// because otherwise it would not react to sound.
-	const TypeInfo * ti = TypeInfo::FindType("BossEye");
+	const PClass * ti = PClass::FindClass("BossEye");
 	if (ti!=NULL)
 	{
 		AActor * def = GetDefaultByType(ti);
@@ -2618,7 +2618,7 @@ void A_SpawnDehackedPickup (AActor *actor)
 
 bool ADehackedPickup::TryPickup (AActor *toucher)
 {
-	const TypeInfo *type = DetermineType ();
+	const PClass *type = DetermineType ();
 	if (type == NULL)
 	{
 		return false;
@@ -2687,7 +2687,7 @@ void ADehackedPickup::Destroy ()
 	Super::Destroy ();
 }
 
-const TypeInfo *ADehackedPickup::DetermineType ()
+const PClass *ADehackedPickup::DetermineType ()
 {
 	// Look at the actor's current sprite to determine what kind of
 	// item to pretend to me.
@@ -2700,7 +2700,7 @@ const TypeInfo *ADehackedPickup::DetermineType ()
 		int lex = memcmp (DehSpriteMappings[mid].Sprite, sprites[sprite].name, 4);
 		if (lex == 0)
 		{
-			return TypeInfo::FindType (DehSpriteMappings[mid].ClassName);
+			return PClass::FindClass (DehSpriteMappings[mid].ClassName);
 		}
 		else if (lex < 0)
 		{
diff --git a/src/d_main.cpp b/src/d_main.cpp
index 70f273243..91b0b0f84 100644
--- a/src/d_main.cpp
+++ b/src/d_main.cpp
@@ -1905,7 +1905,7 @@ void D_DoomMain (void)
 	file[PATH_MAX-1] = 0;
 
 #if defined(_MSC_VER) || defined(__GNUC__)
-	TypeInfo::StaticInit ();
+	PClass::StaticInit ();
 #endif
 
 	atterm (DObject::StaticShutdown);
diff --git a/src/d_net.cpp b/src/d_net.cpp
index 4cba433ea..ee4ad806f 100644
--- a/src/d_net.cpp
+++ b/src/d_net.cpp
@@ -2104,10 +2104,10 @@ void Net_DoCommand (int type, byte **stream, int player)
 	case DEM_SUMMON:
 	case DEM_SUMMONFRIEND:
 		{
-			const TypeInfo *typeinfo;
+			const PClass *typeinfo;
 
 			s = ReadString (stream);
-			typeinfo = TypeInfo::FindType (s);
+			typeinfo = PClass::FindClass (s);
 			if (typeinfo != NULL && typeinfo->ActorInfo != NULL)
 			{
 				AActor *source = players[player].mo;
diff --git a/src/d_player.h b/src/d_player.h
index 07e2fe234..7c12e6972 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -69,8 +69,8 @@ public:
 	virtual bool DoHealingRadius (APlayerPawn *other);
 	virtual void MorphPlayerThink ();
 	virtual void ActivateMorphWeapon ();
-	virtual AWeapon *PickNewWeapon (const TypeInfo *ammotype);
-	virtual AWeapon *BestWeapon (const TypeInfo *ammotype);
+	virtual AWeapon *PickNewWeapon (const PClass *ammotype);
+	virtual AWeapon *BestWeapon (const PClass *ammotype);
 
 	enum EInvulState
 	{
@@ -165,7 +165,7 @@ public:
 
 	userinfo_t	userinfo;				// [RH] who is this?
 	
-	const TypeInfo *cls;				// class of associated PlayerPawn
+	const PClass *cls;				// class of associated PlayerPawn
 
 	float		DesiredFOV;				// desired field of vision
 	float		FOV;					// current field of vision
diff --git a/src/decallib.cpp b/src/decallib.cpp
index 14a98e824..56a4da347 100644
--- a/src/decallib.cpp
+++ b/src/decallib.cpp
@@ -349,9 +349,9 @@ void FDecalLib::ReadAllDecals ()
 		SC_Close ();
 	}
 	// Supporting code to allow specifying decals directly in the DECORATE lump
-	for (i = 0; i < TypeInfo::m_RuntimeActors.Size(); i++)
+	for (i = 0; i < PClass::m_RuntimeActors.Size(); i++)
 	{
-		AActor *def = (AActor*)GetDefaultByType (TypeInfo::m_RuntimeActors[i]);
+		AActor *def = (AActor*)GetDefaultByType (PClass::m_RuntimeActors[i]);
 
 		intptr_t v = (intptr_t)def->DecalGenerator;
 		if (v > 0 && v <= (intptr_t)DecalNames.Size())
@@ -585,26 +585,18 @@ void FDecalLib::ParseDecalGroup ()
 
 void FDecalLib::ParseGenerator ()
 {
-	const TypeInfo *type;
+	const PClass *type;
 	FDecalBase *decal;
 	AActor *actor;
 
 	// Get name of generator (actor)
 	SC_MustGetString ();
-	type = TypeInfo::FindType (sc_String);
+	type = PClass::FindClass (sc_String);
 	if (type == NULL || type->ActorInfo == NULL)
 	{
-		if (type == NULL)
-		{
-			type = TypeInfo::IFindType (sc_String);
-			if (type != NULL)
-			{
-				SC_ScriptError ("%s is not an actor. Did you mean %s?", sc_String, type->Name + 1);
-			}
-		}
 		SC_ScriptError ("%s is not an actor.", sc_String);
 	}
-	actor = (AActor *)type->ActorInfo->Defaults;
+	actor = (AActor *)type->Defaults;
 
 	// Get name of generated decal
 	SC_MustGetString ();
@@ -894,7 +886,7 @@ void FDecalLib::AddDecal (FDecalBase *decal)
 		// Fix references to the old decal so that they use the new one instead.
 		for (unsigned int i = 0; i < node->Users.Size(); ++i)
 		{
-			((AActor *)node->Users[i]->ActorInfo->Defaults)->DecalGenerator = decal;
+			((AActor *)node->Users[i]->Defaults)->DecalGenerator = decal;
 		}
 		decal->Users = node->Users;
 		delete node;
diff --git a/src/decallib.h b/src/decallib.h
index db01d5c69..9428ea11b 100644
--- a/src/decallib.h
+++ b/src/decallib.h
@@ -43,7 +43,7 @@
 class AActor;
 class FDecalTemplate;
 struct FDecalAnimator;
-struct TypeInfo;
+struct PClass;
 class DBaseDecal;
 struct side_s;
 
@@ -60,7 +60,7 @@ protected:
 	FDecalBase *Left, *Right;
 	FName Name;
 	BYTE SpawnID;
-	TArray<const TypeInfo *> Users;	// Which actors generate this decal
+	TArray<const PClass *> Users;	// Which actors generate this decal
 };
 
 class FDecalTemplate : public FDecalBase
diff --git a/src/decorations.cpp b/src/decorations.cpp
index a0c269a5a..548b412fe 100644
--- a/src/decorations.cpp
+++ b/src/decorations.cpp
@@ -323,11 +323,11 @@ static void ParseDecorate (void (*process)(FState *, int))
 {
 	TArray<FState> states;
 	FExtraInfo extra;
-	TypeInfo *type;
-	TypeInfo *parent;
+	PClass *type;
+	PClass *parent;
 	EDefinitionType def;
 	FActorInfo *info;
-	char *typeName;
+	FName typeName;
 	int recursion=0;
 
 	// Get actor class name. The A prefix is added automatically.
@@ -384,11 +384,8 @@ static void ParseDecorate (void (*process)(FState *, int))
 			def = DEF_Decoration;
 		}
 
-		typeName = new char[strlen(sc_String)+2];
-		typeName[0] = 'A';
-		strcpy (&typeName[1], sc_String);
-
-		type = parent->CreateDerivedClass (typeName, parent->SizeOf);
+		typeName = FName(sc_String);
+		type = parent->CreateDerivedClass (typeName, parent->Size);
 		info = type->ActorInfo;
 		info->GameFilter = 0x80;
 		Decorations.Push (info);
@@ -437,20 +434,20 @@ static void ParseDecorate (void (*process)(FState *, int))
 
 		states.Clear ();
 		memset (&extra, 0, sizeof(extra));
-		ParseInsideDecoration (info, (AActor *)(info->Defaults), states, extra, def);
+		ParseInsideDecoration (info, (AActor *)(type->Defaults), states, extra, def);
 
 		info->NumOwnedStates = states.Size();
 		if (info->NumOwnedStates == 0)
 		{
-			SC_ScriptError ("%s does not define any animation frames", typeName + 1);
+			SC_ScriptError ("%s does not define any animation frames", typeName );
 		}
 		else if (extra.SpawnEnd == 0)
 		{
-			SC_ScriptError ("%s does not have a Frames definition", typeName + 1);
+			SC_ScriptError ("%s does not have a Frames definition", typeName );
 		}
 		else if (def == DEF_BreakableDecoration && extra.DeathEnd == 0)
 		{
-			SC_ScriptError ("%s does not have a DeathFrames definition", typeName + 1);
+			SC_ScriptError ("%s does not have a DeathFrames definition", typeName );
 		}
 		else if (extra.IceDeathEnd != 0 && extra.bGenericIceDeath)
 		{
@@ -526,10 +523,10 @@ static void ParseDecorate (void (*process)(FState *, int))
 						info->OwnedStates[extra.DeathStart].Action = A_ScreamAndUnblock;
 					}
 
-					if (extra.DeathHeight == 0) extra.DeathHeight = ((AActor*)(info->Defaults))->height;
+					if (extra.DeathHeight == 0) extra.DeathHeight = ((AActor*)(type->Defaults))->height;
 					info->Class->Meta.SetMetaFixed (AMETA_DeathHeight, extra.DeathHeight);
 				}
-				((AActor *)(info->Defaults))->DeathState = &info->OwnedStates[extra.DeathStart];
+				((AActor *)(type->Defaults))->DeathState = &info->OwnedStates[extra.DeathStart];
 			}
 
 			// Burn states are the same as death states, except they can optionally terminate
@@ -565,10 +562,10 @@ static void ParseDecorate (void (*process)(FState *, int))
 					info->OwnedStates[extra.FireDeathStart].Action = A_ActiveAndUnblock;
 				}
 
-				if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(info->Defaults))->height;
-				info->Class->Meta.SetMetaFixed (AMETA_BurnHeight, extra.BurnHeight);
+				if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height;
+				type->Meta.SetMetaFixed (AMETA_BurnHeight, extra.BurnHeight);
 
-				((AActor *)(info->Defaults))->BDeathState = &info->OwnedStates[extra.FireDeathStart];
+				((AActor *)(type->Defaults))->BDeathState = &info->OwnedStates[extra.FireDeathStart];
 			}
 
 			// Ice states are similar to burn and death, except their final frame enters
@@ -589,31 +586,31 @@ static void ParseDecorate (void (*process)(FState *, int))
 				info->OwnedStates[i].Tics = 2;
 				info->OwnedStates[i].Misc1 = 0;
 				info->OwnedStates[i].Action = A_FreezeDeathChunks;
-				((AActor *)(info->Defaults))->IDeathState = &info->OwnedStates[extra.IceDeathStart];
+				((AActor *)(type->Defaults))->IDeathState = &info->OwnedStates[extra.IceDeathStart];
 			}
 			else if (extra.bGenericIceDeath)
 			{
-				((AActor *)(info->Defaults))->IDeathState = &AActor::States[AActor::S_GENERICFREEZEDEATH];
+				((AActor *)(type->Defaults))->IDeathState = &AActor::States[AActor::S_GENERICFREEZEDEATH];
 			}
 		}
 		if (def == DEF_BreakableDecoration)
 		{
-			((AActor *)(info->Defaults))->flags |= MF_SHOOTABLE;
+			((AActor *)(type->Defaults))->flags |= MF_SHOOTABLE;
 		}
 		if (def == DEF_Projectile)
 		{
 			if (extra.ExplosionRadius > 0)
 			{
-				((ASimpleProjectile *)(info->Defaults))->ExplosionRadius =
+				((ASimpleProjectile *)(type->Defaults))->ExplosionRadius =
 					extra.ExplosionRadius;
-				((ASimpleProjectile *)(info->Defaults))->ExplosionDamage =
+				((ASimpleProjectile *)(type->Defaults))->ExplosionDamage =
 					extra.ExplosionDamage > 0 ? extra.ExplosionDamage : extra.ExplosionRadius;
-				((ASimpleProjectile *)(info->Defaults))->HurtShooter =
+				((ASimpleProjectile *)(type->Defaults))->HurtShooter =
 					!extra.ExplosionShooterImmune;
 			}
-			((AActor *)(info->Defaults))->flags |= MF_DROPOFF|MF_MISSILE;
+			((AActor *)(type->Defaults))->flags |= MF_DROPOFF|MF_MISSILE;
 		}
-		((AActor *)(info->Defaults))->SpawnState = &info->OwnedStates[extra.SpawnStart];
+		((AActor *)(type->Defaults))->SpawnState = &info->OwnedStates[extra.SpawnStart];
 		process (info->OwnedStates, info->NumOwnedStates);
 	}
 }
diff --git a/src/dobject.cpp b/src/dobject.cpp
index b474833d3..7e2715e0c 100644
--- a/src/dobject.cpp
+++ b/src/dobject.cpp
@@ -47,296 +47,23 @@
 #include "r_state.h"
 #include "stats.h"
 
-TArray<TypeInfo *> TypeInfo::m_RuntimeActors;
-TArray<TypeInfo *> TypeInfo::m_Types (256);
-unsigned int TypeInfo::TypeHash[TypeInfo::HASH_SIZE];	// Why can't I use TypeInfo::HASH_SIZE?
-
-#if defined(_MSC_VER) || defined(__GNUC__)
 #include "autosegs.h"
 
-TypeInfo DObject::_StaticType =
+PClass DObject::_StaticType;
+ClassReg DObject::RegistrationInfo =
 {
-	"DObject",
-	NULL,
-	sizeof(DObject),
+	&DObject::_StaticType,			// MyClass
+	"DObject",						// Name
+	NULL,							// ParentType
+	sizeof(DObject),				// SizeOf
+	NULL,							// Pointers
+	&DObject::InPlaceConstructor	// ConstructNative
 };
-
-void TypeInfo::StaticInit ()
-{
-	TAutoSegIterator<TypeInfo *, &CRegHead, &CRegTail> probe;
-
-	while (++probe != NULL)
-	{
-		probe->RegisterType ();
-	}
-}
-#else
-TypeInfo DObject::_StaticType(NULL, "DObject", NULL, sizeof(DObject));
-#endif
+_DECLARE_TI(DObject)
 
 static cycle_t StaleCycles;
 static int StaleCount;
 
-// A harmless non_NULL FlatPointer for classes without pointers.
-static const size_t TheEnd = ~0;
-
-static struct TypeInfoDataFreeer
-{
-	~TypeInfoDataFreeer()
-	{
-		TArray<size_t *> uniqueFPs(64);
-		unsigned int i, j;
-
-		for (i = 0; i < TypeInfo::m_Types.Size(); ++i)
-		{
-			TypeInfo *type = TypeInfo::m_Types[i];
-			if (type->FlatPointers != &TheEnd && type->FlatPointers != type->Pointers)
-			{
-				// FlatPointers are shared by many classes, so we must check for
-				// duplicates and only delete those that are unique.
-				for (j = 0; j < uniqueFPs.Size(); ++j)
-				{
-					if (type->FlatPointers == uniqueFPs[j])
-					{
-						break;
-					}
-				}
-				if (j == uniqueFPs.Size())
-				{
-					uniqueFPs.Push(const_cast<size_t *>(type->FlatPointers));
-				}
-			}
-			// For runtime classes, this call will also delete the TypeInfo.
-			TypeInfo::StaticFreeData (type);
-		}
-		for (i = 0; i < uniqueFPs.Size(); ++i)
-		{
-			delete[] uniqueFPs[i];
-		}
-	}
-} FreeTypeInfoData;
-
-void TypeInfo::StaticFreeData (TypeInfo *type)
-{
-	if (type->ActorInfo != NULL)
-	{
-		if (type->ActorInfo->Defaults != NULL)
-		{
-			delete[] type->ActorInfo->Defaults;
-			type->ActorInfo->Defaults = NULL;
-		}
-	}
-	if (type->bRuntimeClass)
-	{
-		if (type->Name != NULL)
-		{
-			delete[] type->Name;
-		}
-		type->Name = NULL;
-		if (type->ActorInfo != NULL)
-		{
-			if (type->ActorInfo->OwnedStates != NULL)
-			{
-				delete[] type->ActorInfo->OwnedStates;
-				type->ActorInfo->OwnedStates = NULL;
-			}
-			delete type->ActorInfo;
-			type->ActorInfo = NULL;
-		}
-		delete type;
-	}
-}
-
-void TypeInfo::RegisterType ()
-{
-	// Add type to list
-	TypeIndex = m_Types.Push (this);
-
-	// Add type to hash table. Types are inserted into each bucket
-	// lexicographically, and the prefix character is ignored.
-	unsigned int bucket = MakeKey (Name+1) % HASH_SIZE;
-	unsigned int *hashpos = &TypeHash[bucket];
-	while (*hashpos != 0)
-	{
-		int lexx = strcmp (Name+1, m_Types[*hashpos-1]->Name+1);
-		// (The Lexx is the most powerful weapon of destruction
-		//  in the two universes.)
-
-		if (lexx > 0)
-		{ // This type should come later in the chain
-			hashpos = &m_Types[*hashpos-1]->HashNext;
-		}
-		else if (lexx == 0)
-		{ // This type has already been inserted
-			I_FatalError ("Class %s already registered", Name);
-		}
-		else
-		{ // Type comes right here
-			break;
-		}
-	}
-	HashNext = *hashpos;
-	*hashpos = TypeIndex + 1;
-}
-
-// Case-sensitive search (preferred)
-const TypeInfo *TypeInfo::FindType (const char *name)
-{
-	if (name != NULL)
-	{
-		unsigned int index = TypeHash[MakeKey (name) % HASH_SIZE];
-
-		while (index != 0)
-		{
-			int lexx = strcmp (name, m_Types[index-1]->Name + 1);
-			if (lexx > 0)
-			{
-				index = m_Types[index-1]->HashNext;
-			}
-			else if (lexx == 0)
-			{
-				return m_Types[index-1];
-			}
-			else
-			{
-				break;
-			}
-		}
-	}
-	return NULL;
-}
-
-// Case-insensitive search
-const TypeInfo *TypeInfo::IFindType (const char *name)
-{
-	if (name != NULL)
-	{
-		for (int i = 0; i < TypeInfo::m_Types.Size(); i++)
-		{
-			if (stricmp (TypeInfo::m_Types[i]->Name + 1, name) == 0)
-				return TypeInfo::m_Types[i];
-		}
-	}
-	return NULL;
-}
-
-// Create a new object that this type represents
-DObject *TypeInfo::CreateNew () const
-{
-	BYTE *mem = (BYTE *)M_Malloc (SizeOf);
-	ConstructNative (mem);
-	((DObject *)mem)->SetClass (const_cast<TypeInfo *>(this));
-
-	// If this is a scripted extension of a class but not an actor,
-	// initialize any extended space to zero. Actors have defaults, so
-	// we can initialize them better
-	if (ActorInfo != NULL)
-	{
-		AActor *actor = (AActor *)mem;
-		memcpy (&(actor->x), &(((AActor *)ActorInfo->Defaults)->x), SizeOf - ((BYTE *)&actor->x - (BYTE *)actor));
-	}
-	else if (ParentType != 0 &&
-		ConstructNative == ParentType->ConstructNative &&
-		SizeOf > ParentType->SizeOf)
-	{
-		memset (mem + ParentType->SizeOf, 0, SizeOf - ParentType->SizeOf);
-	}
-	return (DObject *)mem;
-}
-
-// Create a new type based on an existing type
-TypeInfo *TypeInfo::CreateDerivedClass (char *name, unsigned int size)
-{
-	TypeInfo *type = new TypeInfo;
-
-	type->Name = name;
-	type->ParentType = this;
-	type->SizeOf = size;
-	type->Pointers = NULL;
-	type->ConstructNative = ConstructNative;
-	type->RegisterType();
-	type->Meta = Meta;
-	type->FlatPointers = NULL;
-	type->bRuntimeClass = true;
-
-	// If this class has an actor info, then any classes derived from it
-	// also need an actor info.
-	if (this->ActorInfo != NULL)
-	{
-		FActorInfo *info = type->ActorInfo = new FActorInfo;
-		info->Class = type;
-		info->Defaults = new BYTE[size];
-		info->GameFilter = GAME_Any;
-		info->SpawnID = 0;
-		info->DoomEdNum = -1;
-		info->OwnedStates = NULL;
-		info->NumOwnedStates = 0;
-
-		memcpy (info->Defaults, ActorInfo->Defaults, SizeOf);
-		if (size > SizeOf)
-		{
-			memset (info->Defaults + SizeOf, 0, size - SizeOf);
-		}
-		m_RuntimeActors.Push (type);
-	}
-	else
-	{
-		type->ActorInfo = NULL;
-	}
-	return type;
-}
-
-// Create the FlatPointers array, if it doesn't exist already.
-// It comprises all the Pointers from superclasses plus this class's own Pointers.
-// If this class does not define any new Pointers, then FlatPointers will be set
-// to the same array as the super class's.
-void TypeInfo::BuildFlatPointers ()
-{
-	if (FlatPointers != NULL)
-	{ // Already built: Do nothing.
-		return;
-	}
-	else if (ParentType == NULL)
-	{ // No parent: FlatPointers is the same as Pointers.
-		if (Pointers == NULL)
-		{ // No pointers: Make FlatPointers a harmless non-NULL.
-			FlatPointers = &TheEnd;
-		}
-		else
-		{
-			FlatPointers = Pointers;
-		}
-	}
-	else
-	{
-		ParentType->BuildFlatPointers ();
-		if (Pointers == NULL)
-		{ // No new pointers: Just use the same FlatPointers as the parent.
-			FlatPointers = ParentType->FlatPointers;
-		}
-		else
-		{ // New pointers: Create a new FlatPointers array and add them.
-			int numPointers, numSuperPointers;
-
-			// Count pointers defined by this class.
-			for (numPointers = 0; Pointers[numPointers] != ~(size_t)0; numPointers++)
-			{ }
-			// Count pointers defined by superclasses.
-			for (numSuperPointers = 0; ParentType->FlatPointers[numSuperPointers] != ~(size_t)0; numSuperPointers++)
-			{ }
-
-			// Concatenate them into a new array
-			size_t *flat = new size_t[numPointers + numSuperPointers + 1];
-			if (numSuperPointers > 0)
-			{
-				memcpy (flat, ParentType->FlatPointers, sizeof(size_t)*numSuperPointers);
-			}
-			memcpy (flat + numSuperPointers, Pointers, sizeof(size_t)*(numPointers+1));
-			FlatPointers = flat;
-		}
-	}
-}
-
 FMetaTable::~FMetaTable ()
 {
 	FreeMeta ();
@@ -467,14 +194,116 @@ const char *FMetaTable::GetMetaString (DWORD id) const
 
 CCMD (dumpclasses)
 {
-	const TypeInfo *root;
+	// This is by no means speed-optimized. But it's an informational console
+	// command that will be executed infrequently, so I don't mind.
+	struct DumpInfo
+	{
+		const PClass *Type;
+		DumpInfo *Next;
+		DumpInfo *Children;
+
+		static DumpInfo *FindType (DumpInfo *root, const PClass *type)
+		{
+			if (root == NULL)
+			{
+				return root;
+			}
+			if (root->Type == type)
+			{
+				return root;
+			}
+			if (root->Next != NULL)
+			{
+				return FindType (root->Next, type);
+			}
+			if (root->Children != NULL)
+			{
+				return FindType (root->Children, type);
+			}
+			return NULL;
+		}
+
+		static DumpInfo *AddType (DumpInfo **root, const PClass *type)
+		{
+			DumpInfo *info, *parentInfo;
+
+			if (*root == NULL)
+			{
+				info = new DumpInfo;
+				info->Type = type;
+				info->Next = NULL;
+				info->Children = *root;
+				*root = info;
+				return info;
+			}
+			if (type->ParentClass == (*root)->Type)
+			{
+				parentInfo = *root;
+			}
+			else if (type == (*root)->Type)
+			{
+				return *root;
+			}
+			else
+			{
+				parentInfo = FindType (*root, type->ParentClass);
+				if (parentInfo == NULL)
+				{
+					parentInfo = AddType (root, type->ParentClass);
+				}
+			}
+			// Has this type already been added?
+			for (info = parentInfo->Children; info != NULL; info = info->Next)
+			{
+				if (info->Type == type)
+				{
+					return info;
+				}
+			}
+			info = new DumpInfo;
+			info->Type = type;
+			info->Next = parentInfo->Children;
+			info->Children = NULL;
+			parentInfo->Children = info;
+			return info;
+		}
+
+		static void PrintTree (DumpInfo *root, int level)
+		{
+			Printf ("%*c%s\n", level, ' ', root->Type->TypeName.GetChars());
+			if (root->Children != NULL)
+			{
+				PrintTree (root->Children, level + 2);
+			}
+			if (root->Next != NULL)
+			{
+				PrintTree (root->Next, level);
+			}
+		}
+
+		static void FreeTree (DumpInfo *root)
+		{
+			if (root->Children != NULL)
+			{
+				FreeTree (root->Children);
+			}
+			if (root->Next != NULL)
+			{
+				FreeTree (root->Next);
+			}
+			delete root;
+		}
+	};
+
 	int i;
 	int shown, omitted;
+	DumpInfo *tree = NULL;
+	const PClass *root = NULL;
 	bool showall = true;
 
 	if (argv.argc() > 1)
 	{
-		root = TypeInfo::IFindType (argv[1]);
+		root = PClass::FindClass (argv[1]);
 		if (root == NULL)
 		{
 			Printf ("Class '%s' not found\n", argv[1]);
@@ -488,20 +317,19 @@ CCMD (dumpclasses)
 			}
 		}
 	}
-	else
-	{
-		root = NULL;
-	}
 
 	shown = omitted = 0;
-	for (i = 0; i < TypeInfo::m_Types.Size(); i++)
+	DumpInfo::AddType (&tree, root != NULL ? root : RUNTIME_CLASS(DObject));
+	for (i = 0; i < PClass::m_Types.Size(); i++)
 	{
+		PClass *cls = PClass::m_Types[i];
 		if (root == NULL ||
-			(TypeInfo::m_Types[i]->IsDescendantOf (root) &&
-			 (showall || TypeInfo::m_Types[i] == root ||
-			  TypeInfo::m_Types[i]->ActorInfo != root->ActorInfo)))
+			(cls->IsDescendantOf (root) &&
+			(showall || cls == root ||
+			cls->ActorInfo != root->ActorInfo)))
 		{
-			Printf (" %s\n", TypeInfo::m_Types[i]->Name + 1);
+			DumpInfo::AddType (&tree, cls);
+//			Printf (" %s\n", PClass::m_Types[i]->Name + 1);
 			shown++;
 		}
 		else
@@ -509,6 +337,8 @@ CCMD (dumpclasses)
 			omitted++;
 		}
 	}
+	DumpInfo::PrintTree (tree, 2);
+	DumpInfo::FreeTree (tree);
 	Printf ("%d classes shown, %d omitted\n", shown, omitted);
 }
 
@@ -517,20 +347,25 @@ TArray<size_t> DObject::FreeIndices (TArray<size_t>::NoInit);
 TArray<DObject *> DObject::ToDestroy (TArray<DObject *>::NoInit);
 bool DObject::Inactive;
 
+void DObject::InPlaceConstructor (void *mem)
+{
+	new ((EInPlace *)mem) DObject;
+}
+
 DObject::DObject ()
 : ObjectFlags(0), Class(0)
 {
 	if (FreeIndices.Pop (Index))
-		Objects[(unsigned int)Index] = this;
+		Objects[Index] = this;
 	else
 		Index = Objects.Push (this);
 }
 
-DObject::DObject (TypeInfo *inClass)
+DObject::DObject (PClass *inClass)
 : ObjectFlags(0), Class(inClass)
 {
 	if (FreeIndices.Pop (Index))
-		Objects[(unsigned int)Index] = this;
+		Objects[Index] = this;
 	else
 		Index = Objects.Push (this);
 }
@@ -616,7 +451,7 @@ void DObject::RemoveFromArray ()
 	}
 	else if (Objects.Size() > Index)
 	{
-		Objects[(unsigned int)Index] = NULL;
+		Objects[Index] = NULL;
 		FreeIndices.Push (Index);
 	}
 }
@@ -631,11 +466,11 @@ void DObject::PointerSubstitution (DObject *old, DObject *notOld)
 		DObject *current = i < highest ? Objects[i] : &bglobal;
 		if (current)
 		{
-			const TypeInfo *info = current->GetClass();
+			const PClass *info = current->GetClass();
 			const size_t *offsets = info->FlatPointers;
 			if (offsets == NULL)
 			{
-				const_cast<TypeInfo *>(info)->BuildFlatPointers();
+				const_cast<PClass *>(info)->BuildFlatPointers();
 				offsets = info->FlatPointers;
 			}
 			while (*offsets != ~(size_t)0)
@@ -699,11 +534,11 @@ void DObject::DestroyScan ()
 		DObject *current = i < highest ? Objects[i] : &bglobal;
 		if (current)
 		{
-			const TypeInfo *info = current->GetClass();
+			const PClass *info = current->GetClass();
 			const size_t *offsets = info->FlatPointers;
 			if (offsets == NULL)
 			{
-				const_cast<TypeInfo *>(info)->BuildFlatPointers();
+				const_cast<PClass *>(info)->BuildFlatPointers();
 				offsets = info->FlatPointers;
 			}
 			while (*offsets != ~(size_t)0)
@@ -778,7 +613,7 @@ void DObject::CheckIfSerialized () const
 			"BUG: %s::Serialize\n"
 			"(or one of its superclasses) needs to call\n"
 			"Super::Serialize\n",
-			StaticType ()->Name);
+			StaticType()->TypeName.GetChars());
 	}
 }
 
diff --git a/src/dobject.h b/src/dobject.h
index f9aab5504..c96ef24f5 100644
--- a/src/dobject.h
+++ b/src/dobject.h
@@ -38,7 +38,7 @@
 #include "tarray.h"
 #include "doomtype.h"
 
-class TypeInfo;
+struct PClass;
 
 class FArchive;
 
@@ -133,15 +133,16 @@ private:
 };
 
 #define RUNTIME_TYPE(object)	(object->GetClass())	// Passed an object, returns the type of that object
-#define RUNTIME_CLASS(cls)		(&cls::_StaticType)		// Passed a class name, returns a TypeInfo representing that class
+#define RUNTIME_CLASS(cls)		(&cls::_StaticType)		// Passed a class name, returns a PClass representing that class
+#define NATIVE_TYPE(object)		(object->StaticType())	// Passed an object, returns the type of the C++ class representing the object
 
 struct ClassReg
 {
-	TypeInfo *MyClass;
+	PClass *MyClass;
 	const char *Name;
-	TypeInfo *ParentType;
+	PClass *ParentType;
 	unsigned int SizeOf;
-	POINTY_TYPE(DObject) *Pointers;
+	const size_t *Pointers;
 	void (*ConstructNative)(void *);
 
 	void RegisterClass();
@@ -151,8 +152,9 @@ enum EInPlace { EC_InPlace };
 
 #define DECLARE_ABSTRACT_CLASS(cls,parent) \
 public: \
-	static TypeInfo _StaticType; \
-	virtual TypeInfo *StaticType() const { return RUNTIME_CLASS(cls); } \
+	static PClass _StaticType; \
+	virtual PClass *StaticType() const { return &_StaticType; } \
+	static ClassReg RegistrationInfo, *RegistrationInfoPtr; \
 private: \
 	typedef parent Super; \
 	typedef cls ThisClass;
@@ -169,44 +171,39 @@ private: \
 #define DECLARE_POINTER(field)	(size_t)&((ThisClass*)1)->field - 1,
 #define END_POINTERS			~0 };
 
-#if !defined(_MSC_VER) && !defined(__GNUC__)
-#       define _IMP_TYPEINFO(cls,ptr,create) \
-	TypeInfo cls::_StaticType (ptr, #cls, RUNTIME_CLASS(cls::Super), sizeof(cls), create);
+#if defined(_MSC_VER)
+#	pragma data_seg(".creg$u")
+#	pragma data_seg()
+#	define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg *cls::RegistrationInfoPtr = &cls::RegistrationInfo;
 #else
-
-#       if defined(_MSC_VER)
-#               pragma data_seg(".creg$u")
-#               pragma data_seg()
-#               define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) TypeInfo *_##cls##AddType = &cls::_StaticType;
-#       else
-#               define _DECLARE_TI(cls) TypeInfo *_##cls##AddType __attribute__((section("creg"))) = &cls::_StaticType;
-#       endif
-
-#       define _IMP_TYPEINFO(cls,ptrs,create) \
-	TypeInfo cls::_StaticType = { \
-#cls, \
-	RUNTIME_CLASS(cls::Super), \
-	sizeof(cls), \
-	ptrs, \
-	create, }; \
-	_DECLARE_TI(cls)
-
+#	define _DECLARE_TI(cls) ClassReg *cls::RegistrationInfoPtr __attribute__((section("creg"))) = &cls::RegistartionInfo;
 #endif
 
+#define _IMP_PCLASS(cls,ptrs,create) \
+	PClass cls::_StaticType; \
+	ClassReg cls::RegistrationInfo = {\
+		RUNTIME_CLASS(cls), \
+		#cls, \
+		RUNTIME_CLASS(cls::Super), \
+		sizeof(cls), \
+		ptrs, \
+		create }; \
+	_DECLARE_TI(cls)
+
 #define _IMP_CREATE_OBJ(cls) \
 	void cls::InPlaceConstructor(void *mem) { new((EInPlace *)mem) cls; }
 
 #define IMPLEMENT_POINTY_CLASS(cls) \
 	_IMP_CREATE_OBJ(cls) \
-	_IMP_TYPEINFO(cls,cls::PointerOffsets,cls::InPlaceConstructor) \
+	_IMP_PCLASS(cls,cls::PointerOffsets,cls::InPlaceConstructor) \
 	const size_t cls::PointerOffsets[] = {
 
 #define IMPLEMENT_CLASS(cls) \
 	_IMP_CREATE_OBJ(cls) \
-	_IMP_TYPEINFO(cls,NULL,cls::InPlaceConstructor) 
+	_IMP_PCLASS(cls,NULL,cls::InPlaceConstructor) 
 
 #define IMPLEMENT_ABSTRACT_CLASS(cls) \
-	_IMP_TYPEINFO(cls,NULL,NULL)
+	_IMP_PCLASS(cls,NULL,NULL)
 
 enum EObjectFlags
 {
@@ -218,27 +215,28 @@ enum EObjectFlags
 
 class DObject
 {
-public: \
-	static TypeInfo _StaticType; \
-	virtual TypeInfo *StaticType() const { return &_StaticType; } \
-	static ClassReg RegistrationInfo;
+public:
+	static PClass _StaticType;
+	virtual PClass *StaticType() const { return &_StaticType; }
+	static ClassReg RegistrationInfo, *RegistrationInfoPtr;
 	static void InPlaceConstructor (void *mem);
-private: \
+private:
 	typedef DObject ThisClass;
 
 	// Per-instance variables. There are three.
 public:
 	DWORD ObjectFlags;			// Flags for this object
 private:
-	TypeInfo *Class;			// This object's type
-	size_t Index;				// This object's index in the global object table
+	PClass *Class;				// This object's type
+	unsigned int Index;			// This object's index in the global object table
 
+public:
 	DObject ();
-	DObject (TypeInfo *inClass);
+	DObject (PClass *inClass);
 	virtual ~DObject ();
 
-	inline bool IsKindOf (const TypeInfo *base) const;
-	inline bool IsA (const TypeInfo *type) const;
+	inline bool IsKindOf (const PClass *base) const;
+	inline bool IsA (const PClass *type) const;
 
 	virtual void Serialize (FArchive &arc);
 
@@ -258,7 +256,7 @@ private:
 
 	static void STACK_ARGS StaticShutdown ();
 
-	TypeInfo *GetClass() const
+	PClass *GetClass() const
 	{
 		if (Class == NULL)
 		{
@@ -269,7 +267,7 @@ private:
 		return Class;
 	}
 
-	void SetClass (TypeInfo *inClass)
+	void SetClass (PClass *inClass)
 	{
 		Class = inClass;
 	}
@@ -285,7 +283,7 @@ private:
 	}
 
 protected:
-	// This form of placement new and delete is for use *only* by TypeInfo's
+	// This form of placement new and delete is for use *only* by PClass's
 	// CreateNew() method. Do not use them for some other purpose.
 	void *operator new(size_t len, EInPlace *mem)
 	{
@@ -312,12 +310,12 @@ private:
 
 #include "dobjtype.h"
 
-inline bool DObject::IsKindOf (const TypeInfo *base) const
+inline bool DObject::IsKindOf (const PClass *base) const
 {
 	return base->IsAncestorOf (GetClass ());
 }
 
-inline bool DObject::IsA (const TypeInfo *type) const
+inline bool DObject::IsA (const PClass *type) const
 {
 	return (type == GetClass());
 }
diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp
new file mode 100644
index 000000000..b9292b8fd
--- /dev/null
+++ b/src/dobjtype.cpp
@@ -0,0 +1,268 @@
+#include "dobject.h"
+#include "i_system.h"
+#include "actor.h"
+#include "autosegs.h"
+
+TArray<PClass *> PClass::m_RuntimeActors;
+TArray<PClass *> PClass::m_Types;
+PClass *PClass::TypeHash[PClass::HASH_SIZE];
+
+// A harmless non_NULL FlatPointer for classes without pointers.
+static const size_t TheEnd = ~0;
+
+static struct TypeInfoDataFreeer
+{
+	~TypeInfoDataFreeer()
+	{
+		TArray<size_t *> uniqueFPs(64);
+		unsigned int i, j;
+
+		for (i = 0; i < PClass::m_Types.Size(); ++i)
+		{
+			PClass *type = PClass::m_Types[i];
+			PClass::m_Types[i] = NULL;
+			if (type->FlatPointers != &TheEnd && type->FlatPointers != type->Pointers)
+			{
+				// FlatPointers are shared by many classes, so we must check for
+				// duplicates and only delete those that are unique.
+				for (j = 0; j < uniqueFPs.Size(); ++j)
+				{
+					if (type->FlatPointers == uniqueFPs[j])
+					{
+						break;
+					}
+				}
+				if (j == uniqueFPs.Size())
+				{
+					uniqueFPs.Push(const_cast<size_t *>(type->FlatPointers));
+				}
+			}
+			// For runtime classes, this call will also delete the PClass.
+			PClass::StaticFreeData (type);
+		}
+		for (i = 0; i < uniqueFPs.Size(); ++i)
+		{
+			delete[] uniqueFPs[i];
+		}
+	}
+} FreeTypeInfoData;
+
+void PClass::StaticFreeData (PClass *type)
+{
+	if (type->Defaults != NULL)
+	{
+		delete[] type->Defaults;
+		type->Defaults = NULL;
+	}
+	if (type->bRuntimeClass)
+	{
+		if (type->ActorInfo != NULL)
+		{
+			if (type->ActorInfo->OwnedStates != NULL)
+			{
+				delete[] type->ActorInfo->OwnedStates;
+				type->ActorInfo->OwnedStates = NULL;
+			}
+			delete type->ActorInfo;
+			type->ActorInfo = NULL;
+		}
+		delete type;
+	}
+}
+
+
+void PClass::StaticInit ()
+{
+	TAutoSegIterator<ClassReg *, &CRegHead, &CRegTail> probe;
+
+	while (++probe != NULL)
+	{
+		probe->RegisterClass ();
+	}
+}
+
+void ClassReg::RegisterClass ()
+{
+	assert (MyClass != NULL);
+
+	// Add type to list
+	MyClass->ClassIndex = PClass::m_Types.Push (MyClass);
+
+	MyClass->TypeName = FName(Name+1);
+	MyClass->ParentClass = ParentType;
+	MyClass->Size = SizeOf;
+	MyClass->Pointers = Pointers;
+	MyClass->ConstructNative = ConstructNative;
+	MyClass->InsertIntoHash ();
+}
+
+void PClass::InsertIntoHash ()
+{
+	// Add class to hash table. Classes are inserted into each bucket
+	// in ascending order by name index.
+	unsigned int bucket = TypeName % HASH_SIZE;
+	PClass **hashpos = &TypeHash[bucket];
+	while (*hashpos != NULL)
+	{
+		int lexx = int(TypeName) - int((*hashpos)->TypeName);
+
+		if (lexx > 0)
+		{ // This type should come later in the chain
+			hashpos = &((*hashpos)->HashNext);
+		}
+		else if (lexx == 0)
+		{ // This type has already been inserted
+			I_FatalError ("Tried to register class '%s' more than once.", TypeName.GetChars());
+		}
+		else
+		{ // Type comes right here
+			break;
+		}
+	}
+	HashNext = *hashpos;
+	*hashpos = this;
+}
+
+// Find a type, passed the name as a string
+const PClass *PClass::FindClass (const char *zaname)
+{
+	FName namename (zaname, true);
+
+	if (namename == NAME_None)
+	{
+		return NULL;
+	}
+	return FindClass (namename);
+}
+
+// Find a type, passed the name as a name
+const PClass *PClass::FindClass (FName zaname)
+{
+	PClass *cls = TypeHash[zaname % HASH_SIZE];
+
+	while (cls != 0)
+	{
+		int lexx = int(zaname) - int(cls->TypeName);
+		if (lexx > 0)
+		{
+			cls = cls->HashNext;
+		}
+		else if (lexx == 0)
+		{
+			return cls;
+		}
+		else
+		{
+			break;
+		}
+	}
+	return NULL;
+}
+
+// Create a new object that this class represents
+DObject *PClass::CreateNew () const
+{
+	BYTE *mem = (BYTE *)M_Malloc (Size);
+
+	// Set this object's defaults before constructing it.
+	memcpy (mem, Defaults, Size);
+
+	ConstructNative (mem);
+	((DObject *)mem)->SetClass (const_cast<PClass *>(this));
+	return (DObject *)mem;
+}
+
+// Create a new class based on an existing class
+PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
+{
+	assert (size >= Size);
+
+	PClass *type = new PClass;
+
+	type->TypeName = name;
+	type->ParentClass = this;
+	type->Size = size;
+	type->Pointers = NULL;
+	type->ConstructNative = ConstructNative;
+	type->ClassIndex = m_Types.Push (type);
+	type->InsertIntoHash();
+	type->Meta = Meta;
+	type->Defaults = new BYTE[size];
+	memcpy (type->Defaults, Defaults, Size);
+	if (size > Size)
+	{
+		memset (type->Defaults + Size, 0, size - Size);
+	}
+	type->FlatPointers = NULL;
+	type->bRuntimeClass = true;
+
+	// If this class has an actor info, then any classes derived from it
+	// also need an actor info.
+	if (this->ActorInfo != NULL)
+	{
+		FActorInfo *info = type->ActorInfo = new FActorInfo;
+		info->Class = type;
+		info->GameFilter = GAME_Any;
+		info->SpawnID = 0;
+		info->DoomEdNum = -1;
+		info->OwnedStates = NULL;
+		info->NumOwnedStates = 0;
+		m_RuntimeActors.Push (type);
+	}
+	else
+	{
+		type->ActorInfo = NULL;
+	}
+	return type;
+}
+
+// Create the FlatPointers array, if it doesn't exist already.
+// It comprises all the Pointers from superclasses plus this class's own Pointers.
+// If this class does not define any new Pointers, then FlatPointers will be set
+// to the same array as the super class's.
+void PClass::BuildFlatPointers ()
+{
+	if (FlatPointers != NULL)
+	{ // Already built: Do nothing.
+		return;
+	}
+	else if (ParentClass == NULL)
+	{ // No parent: FlatPointers is the same as Pointers.
+		if (Pointers == NULL)
+		{ // No pointers: Make FlatPointers a harmless non-NULL.
+			FlatPointers = &TheEnd;
+		}
+		else
+		{
+			FlatPointers = Pointers;
+		}
+	}
+	else
+	{
+		ParentClass->BuildFlatPointers ();
+		if (Pointers == NULL)
+		{ // No new pointers: Just use the same FlatPointers as the parent.
+			FlatPointers = ParentClass->FlatPointers;
+		}
+		else
+		{ // New pointers: Create a new FlatPointers array and add them.
+			int numPointers, numSuperPointers;
+
+			// Count pointers defined by this class.
+			for (numPointers = 0; Pointers[numPointers] != ~(size_t)0; numPointers++)
+			{ }
+			// Count pointers defined by superclasses.
+			for (numSuperPointers = 0; ParentClass->FlatPointers[numSuperPointers] != ~(size_t)0; numSuperPointers++)
+			{ }
+
+			// Concatenate them into a new array
+			size_t *flat = new size_t[numPointers + numSuperPointers + 1];
+			if (numSuperPointers > 0)
+			{
+				memcpy (flat, ParentClass->FlatPointers, sizeof(size_t)*numSuperPointers);
+			}
+			memcpy (flat + numSuperPointers, Pointers, sizeof(size_t)*(numPointers+1));
+			FlatPointers = flat;
+		}
+	}
+}
diff --git a/src/dobjtype.h b/src/dobjtype.h
new file mode 100644
index 000000000..02bbf4d7a
--- /dev/null
+++ b/src/dobjtype.h
@@ -0,0 +1,60 @@
+#ifndef DOBJTYPE_H
+#define DOBJTYPE_H
+
+#ifndef __DOBJECT_H__
+#error You must #include "dobject.h" to get dobjtype.h
+#endif
+
+struct PClass
+{
+	static void StaticInit ();
+	static void StaticFreeData (PClass *type);
+
+	// Per-class information -------------------------------------
+	FName				 TypeName;		// this class's name
+	unsigned int		 Size;			// this class's size
+	PClass				*ParentClass;	// the class this class derives from
+	const size_t		*Pointers;		// object pointers defined by this class *only*
+	const size_t		*FlatPointers;	// object pointers defined by this class and all its superclasses; not initialized by default
+	FActorInfo			*ActorInfo;
+	PClass				*HashNext;
+	FMetaTable			 Meta;
+	BYTE				*Defaults;
+	bool				 bRuntimeClass;	// class was defined at run-time, not compile-time
+	unsigned short		 ClassIndex;
+
+	void (*ConstructNative)(void *);
+
+	// The rest are all functions and static data ----------------
+	void InsertIntoHash ();
+	DObject *CreateNew () const;
+	PClass *CreateDerivedClass (FName name, unsigned int size);
+	void BuildFlatPointers ();
+
+	// Returns true if this type is an ancestor of (or same as) the passed type.
+	bool IsAncestorOf (const PClass *ti) const
+	{
+		while (ti)
+		{
+			if (this == ti)
+				return true;
+			ti = ti->ParentClass;
+		}
+		return false;
+	}
+	inline bool IsDescendantOf (const PClass *ti) const
+	{
+		return ti->IsAncestorOf (this);
+	}
+
+	static const PClass *FindClass (const char *name);
+	static const PClass *FindClass (FName name);
+
+	static TArray<PClass *> m_Types;
+	static TArray<PClass *> m_RuntimeActors;
+
+	enum { HASH_SIZE = 256 };
+	static PClass *TypeHash[HASH_SIZE];
+};
+
+#endif
diff --git a/src/doomtype.h b/src/doomtype.h
index 5422b6c2b..9518b1c70 100644
--- a/src/doomtype.h
+++ b/src/doomtype.h
@@ -38,6 +38,7 @@
 
 #include <limits.h>
 #include "zstring.h"
+#include "name.h"
 
 #ifndef __BYTEBOOL__
 #define __BYTEBOOL__
diff --git a/src/dthinker.cpp b/src/dthinker.cpp
index d1e45196d..c85d2e163 100644
--- a/src/dthinker.cpp
+++ b/src/dthinker.cpp
@@ -336,7 +336,7 @@ void DThinker::Tick ()
 {
 }
 
-FThinkerIterator::FThinkerIterator (const TypeInfo *type, int statnum)
+FThinkerIterator::FThinkerIterator (const PClass *type, int statnum)
 {
 	if ((unsigned)statnum > MAX_STATNUM)
 	{
@@ -353,7 +353,7 @@ FThinkerIterator::FThinkerIterator (const TypeInfo *type, int statnum)
 	m_SearchingFresh = false;
 }
 
-FThinkerIterator::FThinkerIterator (const TypeInfo *type, int statnum, DThinker *prev)
+FThinkerIterator::FThinkerIterator (const PClass *type, int statnum, DThinker *prev)
 {
 	if ((unsigned)statnum > MAX_STATNUM)
 	{
diff --git a/src/dthinker.h b/src/dthinker.h
index 25db5403a..b178f3025 100644
--- a/src/dthinker.h
+++ b/src/dthinker.h
@@ -87,15 +87,15 @@ private:
 class FThinkerIterator
 {
 private:
-	const TypeInfo *m_ParentType;
+	const PClass *m_ParentType;
 	Node *m_CurrThinker;
 	BYTE m_Stat;
 	bool m_SearchStats;
 	bool m_SearchingFresh;
 
 public:
-	FThinkerIterator (const TypeInfo *type, int statnum=MAX_STATNUM+1);
-	FThinkerIterator (const TypeInfo *type, int statnum, DThinker *prev);
+	FThinkerIterator (const PClass *type, int statnum=MAX_STATNUM+1);
+	FThinkerIterator (const PClass *type, int statnum, DThinker *prev);
 	DThinker *Next ();
 	void Reinit ();
 };
diff --git a/src/f_finale.cpp b/src/f_finale.cpp
index e88aa6707..3517967e7 100644
--- a/src/f_finale.cpp
+++ b/src/f_finale.cpp
@@ -536,13 +536,13 @@ extern	gamestate_t 	wipegamestate;
 
 void F_StartCast (void)
 {
-	const TypeInfo *type;
+	const PClass *type;
 	int i;
 
 	// [RH] Set the names and defaults for the cast
 	for (i = 0; castorder[i].type; i++)
 	{
-		type = TypeInfo::FindType (castorder[i].type);
+		type = PClass::FindClass (castorder[i].type);
 		if (type == NULL)
 			castorder[i].info = GetDefault<AActor>();
 		else
@@ -551,13 +551,13 @@ void F_StartCast (void)
 
 	for (i = 0; atkstates[i].type; i++)
 	{
-		type = TypeInfo::FindType (atkstates[i].type);
+		type = PClass::FindClass (atkstates[i].type);
 		if (type != NULL)
 		{
 			if (atkstates[i].melee)
-				atkstates[i].match = ((AActor *)(type->ActorInfo->Defaults))->MeleeState + atkstates[i].ofs;
+				atkstates[i].match = ((AActor *)(type->Defaults))->MeleeState + atkstates[i].ofs;
 			else
-				atkstates[i].match = ((AActor *)(type->ActorInfo->Defaults))->MissileState + atkstates[i].ofs;
+				atkstates[i].match = ((AActor *)(type->Defaults))->MissileState + atkstates[i].ofs;
 		}
 		else
 		{
@@ -565,9 +565,9 @@ void F_StartCast (void)
 		}
 	}
 
-	type = TypeInfo::FindType ("DoomPlayer");
+	type = PClass::FindClass (NAME_DoomPlayer);
 	if (type != NULL)
-		advplayerstate = ((AActor *)(type->ActorInfo->Defaults))->MissileState;
+		advplayerstate = ((AActor *)(type->Defaults))->MissileState;
 
 	wipegamestate = GS_FORCEWIPE;
 	castnum = 0;
diff --git a/src/farchive.cpp b/src/farchive.cpp
index 757248481..46100c544 100644
--- a/src/farchive.cpp
+++ b/src/farchive.cpp
@@ -636,8 +636,8 @@ void FArchive::AttachToFile (FFile &file)
 	}
 	m_Persistent = file.IsPersistent();
 	m_TypeMap = NULL;
-	m_TypeMap = new TypeMap[TypeInfo::m_Types.Size()];
-	for (i = 0; i < TypeInfo::m_Types.Size(); i++)
+	m_TypeMap = new TypeMap[PClass::m_Types.Size()];
+	for (i = 0; i < PClass::m_Types.Size(); i++)
 	{
 		m_TypeMap[i].toArchive = TypeMap::NO_INDEX;
 		m_TypeMap[i].toCurrent = NULL;
@@ -963,7 +963,7 @@ FArchive &FArchive::SerializePointer (void *ptrbase, BYTE **ptr, DWORD elemSize)
 	return *this;
 }
 
-FArchive &FArchive::SerializeObject (DObject *&object, TypeInfo *type)
+FArchive &FArchive::SerializeObject (DObject *&object, PClass *type)
 {
 	if (IsStoring ())
 		return WriteObject (object);
@@ -988,7 +988,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
 	}
 	else
 	{
-		const TypeInfo *type = RUNTIME_TYPE(obj);
+		const PClass *type = RUNTIME_TYPE(obj);
 
 		if (type == RUNTIME_CLASS(DObject))
 		{
@@ -997,7 +997,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
 			id[0] = NULL_OBJ;
 			Write (id, 1);
 		}
-		else if (m_TypeMap[type->TypeIndex].toArchive == TypeMap::NO_INDEX)
+		else if (m_TypeMap[type->ClassIndex].toArchive == TypeMap::NO_INDEX)
 		{
 			// No instances of this class have been written out yet.
 			// Write out the class, then write out the object. If this
@@ -1047,7 +1047,7 @@ FArchive &FArchive::WriteObject (DObject *obj)
 					id[0] = NEW_OBJ;
 					Write (id, 1);
 				}
-				WriteCount (m_TypeMap[type->TypeIndex].toArchive);
+				WriteCount (m_TypeMap[type->ClassIndex].toArchive);
 //				Printf ("Reuse class %s (%u)\n", type->Name, m_File->Tell());
 				MapObject (obj);
 				obj->Serialize (*this);
@@ -1064,10 +1064,10 @@ FArchive &FArchive::WriteObject (DObject *obj)
 	return *this;
 }
 
-FArchive &FArchive::ReadObject (DObject* &obj, TypeInfo *wanttype)
+FArchive &FArchive::ReadObject (DObject* &obj, PClass *wanttype)
 {
 	BYTE objHead;
-	const TypeInfo *type;
+	const PClass *type;
 	BYTE playerNum;
 	DWORD index;
 
@@ -1289,24 +1289,24 @@ DWORD FArchive::FindName (const char *name, unsigned int bucket) const
 	return (DWORD)map;
 }
 
-DWORD FArchive::WriteClass (const TypeInfo *info)
+DWORD FArchive::WriteClass (const PClass *info)
 {
-	if (m_ClassCount >= TypeInfo::m_Types.Size())
+	if (m_ClassCount >= PClass::m_Types.Size())
 	{
 		I_Error ("Too many unique classes have been written.\nOnly %u were registered\n",
-			TypeInfo::m_Types.Size());
+			PClass::m_Types.Size());
 	}
-	if (m_TypeMap[info->TypeIndex].toArchive != TypeMap::NO_INDEX)
+	if (m_TypeMap[info->ClassIndex].toArchive != TypeMap::NO_INDEX)
 	{
-		I_Error ("Attempt to write '%s' twice.\n", info->Name);
+		I_Error ("Attempt to write '%s' twice.\n", info->TypeName.GetChars());
 	}
-	m_TypeMap[info->TypeIndex].toArchive = m_ClassCount;
+	m_TypeMap[info->ClassIndex].toArchive = m_ClassCount;
 	m_TypeMap[m_ClassCount].toCurrent = info;
-	WriteString (info->Name);
+	WriteString (info->TypeName.GetChars());
 	return m_ClassCount++;
 }
 
-const TypeInfo *FArchive::ReadClass ()
+const PClass *FArchive::ReadClass ()
 {
 	struct String {
 		String() { val = NULL; }
@@ -1315,51 +1315,55 @@ const TypeInfo *FArchive::ReadClass ()
 	} typeName;
 	int i;
 
-	if (m_ClassCount >= TypeInfo::m_Types.Size())
+	if (m_ClassCount >= PClass::m_Types.Size())
 	{
 		I_Error ("Too many unique classes have been read.\nOnly %u were registered\n",
-			TypeInfo::m_Types.Size());
+			PClass::m_Types.Size());
 	}
 	operator<< (typeName.val);
-	for (i = 0; i < TypeInfo::m_Types.Size(); i++)
+	FName zaname(typeName.val, true);
+	if (zaname != NAME_None)
 	{
-		if (!strcmp (TypeInfo::m_Types[i]->Name, typeName.val))
+		for (i = 0; i < PClass::m_Types.Size(); i++)
 		{
-			m_TypeMap[i].toArchive = m_ClassCount;
-			m_TypeMap[m_ClassCount].toCurrent = TypeInfo::m_Types[i];
-			m_ClassCount++;
-			return TypeInfo::m_Types[i];
+			if (PClass::m_Types[i]->TypeName == zaname)
+			{
+				m_TypeMap[i].toArchive = m_ClassCount;
+				m_TypeMap[m_ClassCount].toCurrent = PClass::m_Types[i];
+				m_ClassCount++;
+				return PClass::m_Types[i];
+			}
 		}
 	}
 	I_Error ("Unknown class '%s'\n", typeName.val);
 	return NULL;
 }
 
-const TypeInfo *FArchive::ReadClass (const TypeInfo *wanttype)
+const PClass *FArchive::ReadClass (const PClass *wanttype)
 {
-	const TypeInfo *type = ReadClass ();
+	const PClass *type = ReadClass ();
 	if (!type->IsDescendantOf (wanttype))
 	{
 		I_Error ("Expected to extract an object of type '%s'.\n"
 				 "Found one of type '%s' instead.\n",
-			wanttype->Name, type->Name);
+			wanttype->TypeName.GetChars(), type->TypeName.GetChars());
 	}
 	return type;
 }
 
-const TypeInfo *FArchive::ReadStoredClass (const TypeInfo *wanttype)
+const PClass *FArchive::ReadStoredClass (const PClass *wanttype)
 {
 	DWORD index = ReadCount ();
 	if (index >= m_ClassCount)
 	{
 		I_Error ("Class reference too high (%lu; max is %lu)\n", index, m_ClassCount);
 	}
-	const TypeInfo *type = m_TypeMap[index].toCurrent;
+	const PClass *type = m_TypeMap[index].toCurrent;
 	if (!type->IsDescendantOf (wanttype))
 	{
 		I_Error ("Expected to extract an object of type '%s'.\n"
 				 "Found one of type '%s' instead.\n",
-			wanttype->Name, type->Name);
+			wanttype->TypeName.GetChars(), type->TypeName.GetChars());
 	}
 	return type;
 }
@@ -1404,7 +1408,7 @@ DWORD FArchive::FindObjectIndex (const DObject *obj) const
 	return (DWORD)index;
 }
 
-void FArchive::UserWriteClass (const TypeInfo *type)
+void FArchive::UserWriteClass (const PClass *type)
 {
 	BYTE id;
 
@@ -1415,7 +1419,7 @@ void FArchive::UserWriteClass (const TypeInfo *type)
 	}
 	else
 	{
-		if (m_TypeMap[type->TypeIndex].toArchive == TypeMap::NO_INDEX)
+		if (m_TypeMap[type->ClassIndex].toArchive == TypeMap::NO_INDEX)
 		{
 			id = 1;
 			Write (&id, 1);
@@ -1425,12 +1429,12 @@ void FArchive::UserWriteClass (const TypeInfo *type)
 		{
 			id = 0;
 			Write (&id, 1);
-			WriteCount (m_TypeMap[type->TypeIndex].toArchive);
+			WriteCount (m_TypeMap[type->ClassIndex].toArchive);
 		}
 	}
 }
 
-void FArchive::UserReadClass (const TypeInfo *&type)
+void FArchive::UserReadClass (const PClass *&type)
 {
 	BYTE newclass;
 
@@ -1452,7 +1456,7 @@ void FArchive::UserReadClass (const TypeInfo *&type)
 	}
 }
 
-FArchive &operator<< (FArchive &arc, const TypeInfo * &info)
+FArchive &operator<< (FArchive &arc, const PClass * &info)
 {
 	if (arc.IsStoring ())
 	{
diff --git a/src/farchive.h b/src/farchive.h
index 9e79e4273..b8a302841 100644
--- a/src/farchive.h
+++ b/src/farchive.h
@@ -168,8 +168,8 @@ virtual void Read (void *mem, unsigned int len);
 		void WriteCount (DWORD count);
 		DWORD ReadCount ();
 
-		void UserWriteClass (const TypeInfo *info);
-		void UserReadClass (const TypeInfo *&info);
+		void UserWriteClass (const PClass *info);
+		void UserReadClass (const PClass *&info);
 
 		FArchive& operator<< (BYTE &c);
 		FArchive& operator<< (WORD &s);
@@ -180,9 +180,9 @@ virtual void Read (void *mem, unsigned int len);
 		FArchive& operator<< (char *&str);
 		FArchive& operator<< (FName &n);
 		FArchive& SerializePointer (void *ptrbase, BYTE **ptr, DWORD elemSize);
-		FArchive& SerializeObject (DObject *&object, TypeInfo *type);
+		FArchive& SerializeObject (DObject *&object, PClass *type);
 		FArchive& WriteObject (DObject *obj);
-		FArchive& ReadObject (DObject *&obj, TypeInfo *wanttype);
+		FArchive& ReadObject (DObject *&obj, PClass *wanttype);
 
 		void WriteName (const char *name);
 		const char *ReadName ();	// The returned name disappears with the archive, unlike strings
@@ -207,10 +207,10 @@ protected:
 
 		DWORD FindObjectIndex (const DObject *obj) const;
 		DWORD MapObject (const DObject *obj);
-		DWORD WriteClass (const TypeInfo *info);
-		const TypeInfo *ReadClass ();
-		const TypeInfo *ReadClass (const TypeInfo *wanttype);
-		const TypeInfo *ReadStoredClass (const TypeInfo *wanttype);
+		DWORD WriteClass (const PClass *info);
+		const PClass *ReadClass ();
+		const PClass *ReadClass (const PClass *wanttype);
+		const PClass *ReadStoredClass (const PClass *wanttype);
 		DWORD HashObject (const DObject *obj) const;
 		DWORD AddName (const char *name);
 		DWORD AddName (unsigned int start);	// Name has already been added to storage
@@ -228,7 +228,7 @@ protected:
 
 		struct TypeMap
 		{
-			const TypeInfo *toCurrent;	// maps archive type index to execution type index
+			const PClass *toCurrent;	// maps archive type index to execution type index
 			DWORD toArchive;		// maps execution type index to archive type index
 
 			enum { NO_INDEX = 0xffffffff };
@@ -285,7 +285,7 @@ inline FArchive &operator<< (FArchive &arc, T* &object)
 	return arc.SerializeObject ((DObject*&)object, RUNTIME_CLASS(T));
 }
 
-FArchive &operator<< (FArchive &arc, const TypeInfo * &info);
+FArchive &operator<< (FArchive &arc, const PClass * &info);
 
 template<class T>
 inline FArchive &operator<< (FArchive &arc, TArray<T> &self)
diff --git a/src/g_doom/a_doomartifacts.cpp b/src/g_doom/a_doomartifacts.cpp
index 308664dc9..2398bc957 100644
--- a/src/g_doom/a_doomartifacts.cpp
+++ b/src/g_doom/a_doomartifacts.cpp
@@ -67,7 +67,7 @@ public:
 		P_GiveBody (Owner, 100);
 		if (Super::Use (pickup))
 		{
-			const TypeInfo *fistType = TypeInfo::FindType ("Fist");
+			const PClass *fistType = PClass::FindClass ("Fist");
 			if (Owner->player->ReadyWeapon == NULL ||
 				Owner->player->ReadyWeapon->GetClass() != fistType)
 			{
diff --git a/src/g_doom/a_doomglobal.h b/src/g_doom/a_doomglobal.h
index 3c032388c..b64b9a0a9 100644
--- a/src/g_doom/a_doomglobal.h
+++ b/src/g_doom/a_doomglobal.h
@@ -84,7 +84,7 @@ public:
 	void BeginPlay ();
 	void Tick ();
 	void SetWeapon (EMarineWeapon);
-	void SetSprite (const TypeInfo *source);
+	void SetSprite (const PClass *source);
 	void Serialize (FArchive &arc);
 
 protected:
diff --git a/src/g_doom/a_doomplayer.cpp b/src/g_doom/a_doomplayer.cpp
index e58acfa16..ad203140f 100644
--- a/src/g_doom/a_doomplayer.cpp
+++ b/src/g_doom/a_doomplayer.cpp
@@ -101,10 +101,10 @@ void ADoomPlayer::GiveDefaultInventory ()
 
 	player->health = deh.StartHealth;		// [RH] Used to be MAXHEALTH
 	health = deh.StartHealth;
-	fist = player->mo->GiveInventoryType (TypeInfo::FindType ("Fist"));
-	pistol = player->mo->GiveInventoryType (TypeInfo::FindType ("Pistol"));
+	fist = player->mo->GiveInventoryType (PClass::FindClass ("Fist"));
+	pistol = player->mo->GiveInventoryType (PClass::FindClass ("Pistol"));
 	// Adding the pistol automatically adds bullets
-	bullets = player->mo->FindInventory (TypeInfo::FindType ("Clip"));
+	bullets = player->mo->FindInventory (PClass::FindClass ("Clip"));
 	if (bullets != NULL)
 	{
 		bullets->Amount = deh.StartBullets;		// [RH] Used to be 50
diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp
index 3d3394aea..6b072b776 100644
--- a/src/g_doom/a_doomweaps.cpp
+++ b/src/g_doom/a_doomweaps.cpp
@@ -1349,14 +1349,14 @@ void A_BFGSpray (AActor *mo)
 	int 				damage;
 	angle_t 			an;
 	AActor				*thingToHit;
-	const TypeInfo		*spraytype = NULL;
+	const PClass		*spraytype = NULL;
 	int					numrays = 40;
 	int					damagecnt = 15;
 
 	int index = CheckIndex (3, NULL);
 	if (index >= 0) 
 	{
-		spraytype = TypeInfo::FindType ((const char *)StateParameters[index]);
+		spraytype = PClass::FindClass ((const char *)StateParameters[index]);
 		numrays = EvalExpressionI (StateParameters[index+1], mo);
 		if (numrays <= 0)
 			numrays = 40;
diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp
index 22194eb6c..09ca48412 100644
--- a/src/g_doom/a_fatso.cpp
+++ b/src/g_doom/a_fatso.cpp
@@ -171,9 +171,9 @@ void A_FatAttack1 (AActor *self)
 	if (!self->target)
 		return;
 
-	const TypeInfo *spawntype = NULL;
+	const PClass *spawntype = NULL;
 	int index = CheckIndex (1, NULL);
-	if (index >= 0) spawntype = TypeInfo::FindType ((const char *)StateParameters[index]);
+	if (index >= 0) spawntype = PClass::FindClass ((const char *)StateParameters[index]);
 	if (spawntype == NULL) spawntype = RUNTIME_CLASS(AFatShot);
 
 	A_FaceTarget (self);
@@ -199,9 +199,9 @@ void A_FatAttack2 (AActor *self)
 	if (!self->target)
 		return;
 
-	const TypeInfo *spawntype = NULL;
+	const PClass *spawntype = NULL;
 	int index = CheckIndex (1, NULL);
-	if (index >= 0) spawntype = TypeInfo::FindType ((const char *)StateParameters[index]);
+	if (index >= 0) spawntype = PClass::FindClass ((const char *)StateParameters[index]);
 	if (spawntype == NULL) spawntype = RUNTIME_CLASS(AFatShot);
 
 	A_FaceTarget (self);
@@ -227,9 +227,9 @@ void A_FatAttack3 (AActor *self)
 	if (!self->target)
 		return;
 
-	const TypeInfo *spawntype = NULL;
+	const PClass *spawntype = NULL;
 	int index = CheckIndex (1, NULL);
-	if (index >= 0) spawntype = TypeInfo::FindType ((const char *)StateParameters[index]);
+	if (index >= 0) spawntype = PClass::FindClass ((const char *)StateParameters[index]);
 	if (spawntype == NULL) spawntype = RUNTIME_CLASS(AFatShot);
 
 	A_FaceTarget (self);
@@ -262,11 +262,11 @@ void A_Mushroom (AActor *actor)
 {
 	int i, j, n = actor->damage;
 
-	const TypeInfo *spawntype = NULL;
+	const PClass *spawntype = NULL;
 	int index = CheckIndex (1, NULL);
 	if (index >= 0) 
 	{
-		spawntype = TypeInfo::FindType((const char *)StateParameters[index]);
+		spawntype = PClass::FindClass((const char *)StateParameters[index]);
 		n = EvalExpressionI (StateParameters[index+1], actor);
 		if (n == 0)
 			n = actor->damage;
diff --git a/src/g_doom/a_keen.cpp b/src/g_doom/a_keen.cpp
index 289db9e71..b322a0758 100644
--- a/src/g_doom/a_keen.cpp
+++ b/src/g_doom/a_keen.cpp
@@ -65,7 +65,7 @@ void A_KeenDie (AActor *self)
 	// scan the remaining thinkers to see if all Keens are dead
 	AActor *other;
 	TThinkerIterator<AActor> iterator;
-	const TypeInfo *matchClass = self->GetClass ();
+	const PClass *matchClass = self->GetClass ();
 
 	while ( (other = iterator.Next ()) )
 	{
diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp
index f8ced5858..14544b44c 100644
--- a/src/g_doom/a_painelemental.cpp
+++ b/src/g_doom/a_painelemental.cpp
@@ -110,12 +110,12 @@ void A_PainShootSkull (AActor *self, angle_t angle)
 	angle_t an;
 	int prestep;
 
-	const TypeInfo *spawntype = NULL;
+	const PClass *spawntype = NULL;
 
 	int index=CheckIndex(1, NULL);
 	if (index>=0) 
 	{
-		spawntype = TypeInfo::FindType((const char *)StateParameters[index]);
+		spawntype = PClass::FindClass((const char *)StateParameters[index]);
 	}
 	if (spawntype == NULL) spawntype = RUNTIME_CLASS(ALostSoul);
 
diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp
index 14685b1c8..4be5554f8 100644
--- a/src/g_doom/a_scriptedmarine.cpp
+++ b/src/g_doom/a_scriptedmarine.cpp
@@ -497,7 +497,7 @@ void A_M_BerserkPunch (AActor *self)
 //
 //============================================================================
 
-void P_GunShot2 (AActor *mo, bool accurate, int pitch, const TypeInfo *pufftype)
+void P_GunShot2 (AActor *mo, bool accurate, int pitch, const PClass *pufftype)
 {
 	angle_t 	angle;
 	int 		damage;
@@ -964,7 +964,7 @@ void AScriptedMarine::SetWeapon (EMarineWeapon type)
 	}
 }
 
-void AScriptedMarine::SetSprite (const TypeInfo *source)
+void AScriptedMarine::SetSprite (const PClass *source)
 {
 	if (source == NULL || source->ActorInfo == NULL)
 	{ // A valid actor class wasn't passed, so use the standard sprite
diff --git a/src/g_doom/doom_sbar.cpp b/src/g_doom/doom_sbar.cpp
index 6049a3dd1..dea30e2b5 100644
--- a/src/g_doom/doom_sbar.cpp
+++ b/src/g_doom/doom_sbar.cpp
@@ -332,7 +332,7 @@ private:
 		{
 			for (j = 0; j < MAX_WEAPONS_PER_SLOT; j++)
 			{
-				const TypeInfo *weap = LocalWeapons.Slots[i+2].GetWeapon (j);
+				const PClass *weap = LocalWeapons.Slots[i+2].GetWeapon (j);
 				if (weap != NULL && CPlayer->mo->FindInventory (weap) != NULL)
 				{
 					arms[i] = 1;
@@ -387,12 +387,12 @@ private:
 
 	void DrawAmmoStats ()
 	{
-		static const char *const ammoTypes[4] =
+		static const ENamedName ammoTypes[4] =
 		{
-			"Clip",
-			"Shell",
-			"RocketAmmo",
-			"Cell"
+			NAME_Clip,
+			NAME_Shell,
+			NAME_RocketAmmo,
+			NAME_Cell
 		};
 		int ammo[4], maxammo[4];
 		int i;
@@ -400,7 +400,7 @@ private:
 		// Catalog the player's ammo
 		for (i = 0; i < 4; i++)
 		{
-			const TypeInfo *type = TypeInfo::FindType (ammoTypes[i]);
+			const PClass *type = PClass::FindClass (ammoTypes[i]);
 			AInventory *item = CPlayer->mo->FindInventory (type);
 			if (item != NULL)
 			{
diff --git a/src/g_game.cpp b/src/g_game.cpp
index 49042556b..3c5f518f1 100644
--- a/src/g_game.cpp
+++ b/src/g_game.cpp
@@ -373,7 +373,7 @@ CCMD (use)
 {
 	if (argv.argc() > 1 && m_Instigator != NULL)
 	{
-		SendItemUse = m_Instigator->FindInventory (TypeInfo::IFindType (argv[1]));
+		SendItemUse = m_Instigator->FindInventory (PClass::FindClass (argv[1]));
 	}
 }
 
@@ -386,17 +386,17 @@ CCMD (drop)
 {
 	if (argv.argc() > 1 && m_Instigator != NULL)
 	{
-		SendItemDrop = m_Instigator->FindInventory (TypeInfo::IFindType (argv[1]));
+		SendItemDrop = m_Instigator->FindInventory (PClass::FindClass (argv[1]));
 	}
 }
 
 CCMD (useflechette)
 { // Select from one of arti_poisonbag1-3, whichever the player has
-	static const char *bagnames[3] =
+	static const ENamedName bagnames[3] =
 	{
-		"ArtiPoisonBag1",
-		"ArtiPoisonBag2",
-		"ArtiPoisonBag3"
+		NAME_ArtiPoisonBag1,
+		NAME_ArtiPoisonBag2,
+		NAME_ArtiPoisonBag3
 	};
 	int i, j;
 
@@ -407,7 +407,7 @@ CCMD (useflechette)
 
 	for (j = 0; j < 3; ++j)
 	{
-		const TypeInfo *type = TypeInfo::FindType (bagnames[(i+j)%3]);
+		const PClass *type = PClass::FindClass (bagnames[(i+j)%3]);
 		AInventory *item;
 		if (type != NULL && (item = m_Instigator->FindInventory (type)))
 		{
@@ -421,7 +421,7 @@ CCMD (select)
 {
 	if (argv.argc() > 1)
 	{
-		AInventory *item = m_Instigator->FindInventory (TypeInfo::FindType (argv[1]));
+		AInventory *item = m_Instigator->FindInventory (PClass::FindClass (argv[1]));
 		if (item != NULL)
 		{
 			m_Instigator->player->InvSel = item;
@@ -1109,7 +1109,7 @@ void G_PlayerReborn (int player)
 	userinfo_t  userinfo;	// [RH] Save userinfo
 	botskill_t  b_skill;//Added by MC:
 	APlayerPawn *actor;
-	const TypeInfo *cls;
+	const PClass *cls;
 	char		*log;
 
 	p = &players[player];
diff --git a/src/g_heretic/a_hereticplayer.cpp b/src/g_heretic/a_hereticplayer.cpp
index 6e8b279ba..e6237cee6 100644
--- a/src/g_heretic/a_hereticplayer.cpp
+++ b/src/g_heretic/a_hereticplayer.cpp
@@ -135,10 +135,10 @@ void AHereticPlayer::GiveDefaultInventory ()
 	AInventory *wand, *ammo;
 
 	player->health = GetDefault()->health;
-	player->mo->GiveInventoryType (TypeInfo::FindType ("Staff"));
-	wand = player->mo->GiveInventoryType (TypeInfo::FindType ("GoldWand"));
+	player->mo->GiveInventoryType (PClass::FindClass ("Staff"));
+	wand = player->mo->GiveInventoryType (PClass::FindClass ("GoldWand"));
 	// Adding the gold wand automatically adds its ammo
-	ammo = player->mo->FindInventory (TypeInfo::FindType ("GoldWandAmmo"));
+	ammo = player->mo->FindInventory (PClass::FindClass ("GoldWandAmmo"));
 	ammo->Amount = 50;
 	player->ReadyWeapon = player->PendingWeapon = static_cast<AWeapon *> (wand);
 }
diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp
index d440a6be5..6c8c58dc6 100644
--- a/src/g_heretic/a_hereticweaps.cpp
+++ b/src/g_heretic/a_hereticweaps.cpp
@@ -1794,7 +1794,7 @@ void A_GauntletAttack (AActor *actor)
 	int randVal;
 	fixed_t dist;
 	player_t *player;
-	const TypeInfo *pufftype;
+	const PClass *pufftype;
 	AInventory *power;
 
 	if (NULL == (player = actor->player))
@@ -2056,7 +2056,7 @@ END_DEFAULTS
 
 int ABlasterFX1::DoSpecialDamage (AActor *target, int damage)
 {
-	if (target->IsKindOf (TypeInfo::FindType ("Ironlich")))
+	if (target->IsKindOf (PClass::FindClass ("Ironlich")))
 	{ // Less damage to Ironlich bosses
 		damage = pr_bfx1() & 1;
 		if (!damage)
@@ -2133,7 +2133,7 @@ END_DEFAULTS
 
 int ARipper::DoSpecialDamage (AActor *target, int damage)
 {
-	if (target->IsKindOf (TypeInfo::FindType ("Ironlich")))
+	if (target->IsKindOf (PClass::FindClass ("Ironlich")))
 	{ // Less damage to Ironlich bosses
 		damage = pr_ripd() & 1;
 		if (!damage)
diff --git a/src/g_heretic/heretic_sbar.cpp b/src/g_heretic/heretic_sbar.cpp
index 3eefda5c7..71fc52f44 100644
--- a/src/g_heretic/heretic_sbar.cpp
+++ b/src/g_heretic/heretic_sbar.cpp
@@ -701,7 +701,7 @@ private:
 //
 //---------------------------------------------------------------------------
 
-	void FlashItem (const TypeInfo *itemtype)
+	void FlashItem (const PClass *itemtype)
 	{
 		ArtifactFlash = 4;
 	}
diff --git a/src/g_hexen/a_centaur.cpp b/src/g_hexen/a_centaur.cpp
index fafe5f6e7..67a72d188 100644
--- a/src/g_hexen/a_centaur.cpp
+++ b/src/g_hexen/a_centaur.cpp
@@ -297,7 +297,7 @@ void A_CentaurAttack2 (AActor *actor)
 
 void A_CentaurDropStuff (AActor *actor)
 {
-	const TypeInfo *const DropTypes[] =
+	const PClass *const DropTypes[] =
 	{
 		RUNTIME_CLASS(ACentaurSword),
 		RUNTIME_CLASS(ACentaurShield)
diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp
index 71da48237..0188d852b 100644
--- a/src/g_hexen/a_clericholy.cpp
+++ b/src/g_hexen/a_clericholy.cpp
@@ -892,7 +892,7 @@ void AClericWeaponPiece::BeginPlay ()
 
 void A_DropWraithvergePieces (AActor *actor)
 {
-	static const TypeInfo *pieces[3] =
+	static const PClass *pieces[3] =
 	{
 		RUNTIME_CLASS(ACWeaponPiece1),
 		RUNTIME_CLASS(ACWeaponPiece2),
diff --git a/src/g_hexen/a_clericplayer.cpp b/src/g_hexen/a_clericplayer.cpp
index dd9c4fd9f..4a7deab12 100644
--- a/src/g_hexen/a_clericplayer.cpp
+++ b/src/g_hexen/a_clericplayer.cpp
@@ -125,7 +125,7 @@ void AClericPlayer::GiveDefaultInventory ()
 {
 	player->health = GetDefault()->health;
 	player->ReadyWeapon = player->PendingWeapon = static_cast<AWeapon *>
-		(GiveInventoryType (TypeInfo::FindType ("CWeapMace")));
+		(GiveInventoryType (PClass::FindClass ("CWeapMace")));
 
 	GiveInventoryType (RUNTIME_CLASS(AHexenArmor));
 	AHexenArmor *armor = FindInventory<AHexenArmor>();
diff --git a/src/g_hexen/a_demons.cpp b/src/g_hexen/a_demons.cpp
index f833f1ac5..751943b2b 100644
--- a/src/g_hexen/a_demons.cpp
+++ b/src/g_hexen/a_demons.cpp
@@ -19,7 +19,7 @@ void A_DemonAttack2_2 (AActor *);
 void A_DemonDeath (AActor *);
 void A_Demon2Death (AActor *);
 
-static void TossChunks (AActor *, const TypeInfo *const chunks[]);
+static void TossChunks (AActor *, const PClass *const chunks[]);
 
 // Demon, type 1 (green, like D'Sparil's) -----------------------------------
 
@@ -605,7 +605,7 @@ void A_DemonAttack2_2 (AActor *actor)
 
 void A_DemonDeath (AActor *actor)
 {
-	const TypeInfo *const ChunkTypes[] =
+	const PClass *const ChunkTypes[] =
 	{
 		RUNTIME_CLASS(ADemon1Chunk5),
 		RUNTIME_CLASS(ADemon1Chunk4),
@@ -625,7 +625,7 @@ void A_DemonDeath (AActor *actor)
 
 void A_Demon2Death (AActor *actor)
 {
-	const TypeInfo *const ChunkTypes[] =
+	const PClass *const ChunkTypes[] =
 	{
 		RUNTIME_CLASS(ADemon2Chunk5),
 		RUNTIME_CLASS(ADemon2Chunk4),
@@ -637,7 +637,7 @@ void A_Demon2Death (AActor *actor)
 	TossChunks (actor, ChunkTypes);
 }
 
-static void TossChunks (AActor *actor, const TypeInfo *const chunks[])
+static void TossChunks (AActor *actor, const PClass *const chunks[])
 {
 	AActor *mo;
 	angle_t angle;
diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp
index 01850563e..6cd88fc5d 100644
--- a/src/g_hexen/a_fighteraxe.cpp
+++ b/src/g_hexen/a_fighteraxe.cpp
@@ -361,7 +361,7 @@ void A_FAxeAttack (AActor *actor)
 	int useMana;
 	player_t *player;
 	AWeapon *weapon;
-	const TypeInfo *pufftype;
+	const PClass *pufftype;
 
 	if (NULL == (player = actor->player))
 	{
diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp
index 49ad47dd8..719ce05ee 100644
--- a/src/g_hexen/a_fighterplayer.cpp
+++ b/src/g_hexen/a_fighterplayer.cpp
@@ -123,7 +123,7 @@ void AFighterPlayer::GiveDefaultInventory ()
 {
 	player->health = GetDefault()->health;
 	player->ReadyWeapon = player->PendingWeapon = static_cast<AWeapon *>
-		(GiveInventoryType (TypeInfo::FindType ("FWeapFist")));
+		(GiveInventoryType (PClass::FindClass ("FWeapFist")));
 
 	GiveInventoryType (RUNTIME_CLASS(AHexenArmor));
 	AHexenArmor *armor = FindInventory<AHexenArmor>();
@@ -269,7 +269,7 @@ void A_FPunchAttack (AActor *actor)
 	fixed_t power;
 	int i;
 	player_t *player;
-	const TypeInfo *pufftype;
+	const PClass *pufftype;
 
 	if (NULL == (player = actor->player))
 	{
diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp
index 5964c5ae8..e39828a83 100644
--- a/src/g_hexen/a_fighterquietus.cpp
+++ b/src/g_hexen/a_fighterquietus.cpp
@@ -367,7 +367,7 @@ void A_FSwordFlames (AActor *actor)
 
 void A_DropQuietusPieces (AActor *actor)
 {
-	static const TypeInfo *pieces[3] =
+	static const PClass *pieces[3] =
 	{
 		RUNTIME_CLASS(AFWeaponPiece1),
 		RUNTIME_CLASS(AFWeaponPiece2),
diff --git a/src/g_hexen/a_firedemon.cpp b/src/g_hexen/a_firedemon.cpp
index 5e87c2e6e..ba5a6ffb5 100644
--- a/src/g_hexen/a_firedemon.cpp
+++ b/src/g_hexen/a_firedemon.cpp
@@ -348,7 +348,7 @@ void A_FiredSpawnRock (AActor *actor)
 {
 	AActor *mo;
 	int x,y,z;
-	const TypeInfo *rtype;
+	const PClass *rtype;
 
 	switch (pr_firedemonrock() % 5)
 	{
diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp
index a8191c3a0..880014c88 100644
--- a/src/g_hexen/a_flechette.cpp
+++ b/src/g_hexen/a_flechette.cpp
@@ -325,7 +325,7 @@ AInventory *AArtiPoisonBag::CreateCopy (AActor *other)
 	}
 
 	AInventory *copy;
-	const TypeInfo *spawntype;
+	const PClass *spawntype;
 
 	if (other->IsKindOf (RUNTIME_CLASS(AClericPlayer)))
 	{
diff --git a/src/g_hexen/a_fog.cpp b/src/g_hexen/a_fog.cpp
index 47b70c77d..9c602e255 100644
--- a/src/g_hexen/a_fog.cpp
+++ b/src/g_hexen/a_fog.cpp
@@ -151,7 +151,7 @@ END_DEFAULTS
 
 void A_FogSpawn (AActor *actor)
 {
-	static const TypeInfo *fogs[3] =
+	static const PClass *fogs[3] =
 	{
 		RUNTIME_CLASS(AFogPatchSmall),
 		RUNTIME_CLASS(AFogPatchMedium),
diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp
index cfef1b912..030ef38b8 100644
--- a/src/g_hexen/a_heresiarch.cpp
+++ b/src/g_hexen/a_heresiarch.cpp
@@ -710,7 +710,7 @@ void A_SorcBallOrbit(AActor *ball)
 
 	if (!ball->IsKindOf (RUNTIME_CLASS(ASorcBall)))
 	{
-		I_Error ("Corrupted sorcerer:\nTried to use a %s", RUNTIME_TYPE(ball)->Name+1);
+		I_Error ("Corrupted sorcerer:\nTried to use a %s", RUNTIME_TYPE(ball)->TypeName.GetChars());
 	}
 	actor = static_cast<ASorcBall *> (ball);
 
diff --git a/src/g_hexen/a_hexenglobal.h b/src/g_hexen/a_hexenglobal.h
index e099e235e..4d1fcdd3e 100644
--- a/src/g_hexen/a_hexenglobal.h
+++ b/src/g_hexen/a_hexenglobal.h
@@ -30,7 +30,7 @@ class AHeresiarch : public AActor
 {
 	DECLARE_ACTOR (AHeresiarch, AActor)
 public:
-	const TypeInfo *StopBall;
+	const PClass *StopBall;
 
 	void Serialize (FArchive &arc);
 	void Die (AActor *source, AActor *inflictor);
@@ -72,7 +72,7 @@ public:
 protected:
 	virtual bool MatchPlayerClass (AActor *toucher);
 	virtual const char *PieceMessage ();
-	const TypeInfo *FourthWeaponClass;
+	const PClass *FourthWeaponClass;
 	int PieceValue;
 	AInventory *TempFourthWeapon;
 	bool PrivateShouldStay ();
diff --git a/src/g_hexen/a_iceguy.cpp b/src/g_hexen/a_iceguy.cpp
index 019788e9b..a669a7fa8 100644
--- a/src/g_hexen/a_iceguy.cpp
+++ b/src/g_hexen/a_iceguy.cpp
@@ -263,7 +263,7 @@ END_DEFAULTS
 
 // Wisp types, for randomness below -----------------------------------------
 
-static const TypeInfo *const WispTypes[2] =
+static const PClass *const WispTypes[2] =
 {
 	RUNTIME_CLASS(AIceGuyWisp1),
 	RUNTIME_CLASS(AIceGuyWisp2)
diff --git a/src/g_hexen/a_korax.cpp b/src/g_hexen/a_korax.cpp
index 8ae0943ac..f6b7855cc 100644
--- a/src/g_hexen/a_korax.cpp
+++ b/src/g_hexen/a_korax.cpp
@@ -71,10 +71,10 @@ void A_KSpiritRoam (AActor *);
 void A_KBolt (AActor *);
 void A_KBoltRaise (AActor *);
 
-void KoraxFire (AActor *actor, const TypeInfo *type, int arm);
+void KoraxFire (AActor *actor, const PClass *type, int arm);
 void KSpiritInit (AActor *spirit, AActor *korax);
 AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
-	AActor *source, AActor *dest, const TypeInfo *type);
+	AActor *source, AActor *dest, const PClass *type);
 
 extern void SpawnSpiritTail (AActor *spirit);
 
@@ -395,11 +395,11 @@ void A_KoraxMissile (AActor *actor)
 
 	int type = pr_koraxmissile()%6;
 	int i;
-	const TypeInfo *info;
+	const PClass *info;
 
 	S_Sound (actor, CHAN_VOICE, "KoraxAttack", 1, ATTN_NORM);
 
-	info = TypeInfo::FindType (choices[type].type);
+	info = PClass::FindClass (choices[type].type);
 	if (info == NULL)
 	{
 		I_Error ("Unknown Korax missile: %s\n", choices[type].type);
@@ -464,7 +464,7 @@ void A_KoraxCommand (AActor *actor)
 //
 //============================================================================
 
-void KoraxFire (AActor *actor, const TypeInfo *type, int arm)
+void KoraxFire (AActor *actor, const PClass *type, int arm)
 {
 	static const int extension[6] =
 	{
@@ -675,7 +675,7 @@ void A_KBoltRaise (AActor *actor)
 //============================================================================
 
 AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
-	AActor *source, AActor *dest, const TypeInfo *type)
+	AActor *source, AActor *dest, const PClass *type)
 {
 	AActor *th;
 	angle_t an;
diff --git a/src/g_hexen/a_mageplayer.cpp b/src/g_hexen/a_mageplayer.cpp
index 0356a48f6..48fdbe072 100644
--- a/src/g_hexen/a_mageplayer.cpp
+++ b/src/g_hexen/a_mageplayer.cpp
@@ -122,7 +122,7 @@ void AMagePlayer::GiveDefaultInventory ()
 {
 	player->health = GetDefault()->health;
 	player->ReadyWeapon = player->PendingWeapon = static_cast<AWeapon *>
-		(GiveInventoryType (TypeInfo::FindType ("MWeapWand")));
+		(GiveInventoryType (PClass::FindClass ("MWeapWand")));
 	
 	GiveInventoryType (RUNTIME_CLASS(AHexenArmor));
 	AHexenArmor *armor = FindInventory<AHexenArmor>();
diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp
index 602e2ffb2..2a21e5aac 100644
--- a/src/g_hexen/a_magestaff.cpp
+++ b/src/g_hexen/a_magestaff.cpp
@@ -486,7 +486,7 @@ void A_MStaffTrack (AActor *actor)
 
 void A_DropBloodscourgePieces (AActor *actor)
 {
-	static const TypeInfo *pieces[3] =
+	static const PClass *pieces[3] =
 	{
 		RUNTIME_CLASS(AMWeaponPiece1),
 		RUNTIME_CLASS(AMWeaponPiece2),
diff --git a/src/g_hexen/a_mana.cpp b/src/g_hexen/a_mana.cpp
index e2cfb78dc..67f96ace0 100644
--- a/src/g_hexen/a_mana.cpp
+++ b/src/g_hexen/a_mana.cpp
@@ -100,7 +100,7 @@ protected:
 	{
 		return GStrings("TXT_MANA_BOTH");
 	}
-	bool GiveMana (AActor *other, const TypeInfo *type)
+	bool GiveMana (AActor *other, const PClass *type)
 	{
 		AInventory *mana = other->FindInventory (type);
 		if (mana == NULL)
@@ -164,7 +164,7 @@ public:
 	bool Use (bool pickup);
 	const char *PickupMessage ();
 protected:
-	bool FillMana (const TypeInfo *type);
+	bool FillMana (const PClass *type);
 };
 
 FState AArtiBoostMana::States[] =
@@ -191,7 +191,7 @@ bool AArtiBoostMana::Use (bool pickup)
 	return success;
 }
 
-bool AArtiBoostMana::FillMana (const TypeInfo *type)
+bool AArtiBoostMana::FillMana (const PClass *type)
 {
 	AInventory *mana = Owner->FindInventory (type);
 	if (mana == NULL)
diff --git a/src/g_hexen/a_serpent.cpp b/src/g_hexen/a_serpent.cpp
index 503ecd397..842100957 100644
--- a/src/g_hexen/a_serpent.cpp
+++ b/src/g_hexen/a_serpent.cpp
@@ -619,7 +619,7 @@ void A_SerpentHeadPop (AActor *actor)
 void A_SerpentSpawnGibs (AActor *actor)
 {
 	AActor *mo;
-	static const TypeInfo *const GibTypes[] =
+	static const PClass *const GibTypes[] =
 	{
 		RUNTIME_CLASS(ASerpentGib3),
 		RUNTIME_CLASS(ASerpentGib2),
diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp
index fec74caf3..81ff22a9e 100644
--- a/src/g_hexen/a_teleportother.cpp
+++ b/src/g_hexen/a_teleportother.cpp
@@ -165,7 +165,7 @@ IMPLEMENT_STATELESS_ACTOR (ATelOtherFX5, Any, -1, 0)
 	PROP_SpawnState (S_TELO_FX5)
 END_DEFAULTS
 
-static void TeloSpawn (AActor *source, const TypeInfo *type)
+static void TeloSpawn (AActor *source, const PClass *type)
 {
 	AActor *fx;
 
diff --git a/src/g_hexen/hexen_sbar.cpp b/src/g_hexen/hexen_sbar.cpp
index 83f2617e6..715fbb560 100644
--- a/src/g_hexen/hexen_sbar.cpp
+++ b/src/g_hexen/hexen_sbar.cpp
@@ -25,7 +25,7 @@ public:
 	void Unload ();
 	bool CheckModified ();
 
-	void SetVial (FTexture *pic, AActor *actor, const TypeInfo *manaType);
+	void SetVial (FTexture *pic, AActor *actor, const PClass *manaType);
 
 protected:
 	BYTE Pixels[5*24];
@@ -89,7 +89,7 @@ const BYTE *FManaBar::GetPixels ()
 	return Pixels;
 }
 
-void FManaBar::SetVial (FTexture *pic, AActor *actor, const TypeInfo *manaType)
+void FManaBar::SetVial (FTexture *pic, AActor *actor, const PClass *manaType)
 {
 	int level;
 	AInventory *ammo;
@@ -1035,7 +1035,7 @@ private:
 //
 //---------------------------------------------------------------------------
 
-	void FlashItem (const TypeInfo *itemtype)
+	void FlashItem (const PClass *itemtype)
 	{
 		ArtifactFlash = 4;
 	}
diff --git a/src/g_level.cpp b/src/g_level.cpp
index 111dbbe3d..fa476a386 100644
--- a/src/g_level.cpp
+++ b/src/g_level.cpp
@@ -772,7 +772,7 @@ static void ParseMapInfoLower (MapInfoHandler *handlers,
 
 		case MITYPE_REDIRECT:
 			SC_MustGetString ();
-			levelinfo->RedirectType = TypeInfo::IFindType (sc_String);
+			levelinfo->RedirectType = PClass::FindClass (sc_String);
 			if (levelinfo->RedirectType == NULL ||
 				!(levelinfo->RedirectType->IsDescendantOf (RUNTIME_CLASS(AInventory))))
 			{
diff --git a/src/g_level.h b/src/g_level.h
index 80b972295..66102239c 100644
--- a/src/g_level.h
+++ b/src/g_level.h
@@ -148,7 +148,7 @@ struct level_info_s
 
 	// Redirection: If any player is carrying the specified item, then
 	// you go to the RedirectMap instead of this one.
-	const TypeInfo *RedirectType;
+	const PClass *RedirectType;
 	char		RedirectMap[9];
 
 	char		enterpic[9];
diff --git a/src/g_raven/a_artiegg.cpp b/src/g_raven/a_artiegg.cpp
index b74bd03ce..e39c3d0eb 100644
--- a/src/g_raven/a_artiegg.cpp
+++ b/src/g_raven/a_artiegg.cpp
@@ -21,7 +21,7 @@ static FRandom pr_morphmonst ("MorphMonster");
 //
 //---------------------------------------------------------------------------
 
-bool P_MorphPlayer (player_t *p, const TypeInfo *spawntype)
+bool P_MorphPlayer (player_t *p, const PClass *spawntype)
 {
 	AInventory *item;
 	APlayerPawn *morphed;
@@ -193,7 +193,7 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
 //
 //---------------------------------------------------------------------------
 
-bool P_MorphMonster (AActor *actor, const TypeInfo *spawntype)
+bool P_MorphMonster (AActor *actor, const PClass *spawntype)
 {
 	AActor *morphed;
 
@@ -329,11 +329,11 @@ int AEggFX::DoSpecialDamage (AActor *target, int damage)
 {
 	if (target->player)
 	{
-		P_MorphPlayer (target->player, TypeInfo::FindType ("ChickenPlayer"));
+		P_MorphPlayer (target->player, PClass::FindClass (NAME_ChickenPlayer));
 	}
 	else
 	{
-		P_MorphMonster (target, TypeInfo::FindType ("Chicken"));
+		P_MorphMonster (target, PClass::FindClass (NAME_Chicken));
 	}
 	return -1;
 }
@@ -422,11 +422,11 @@ int APorkFX::DoSpecialDamage (AActor *target, int damage)
 {
 	if (target->player)
 	{
-		P_MorphPlayer (target->player, TypeInfo::FindType ("PigPlayer"));
+		P_MorphPlayer (target->player, PClass::FindClass (NAME_PigPlayer));
 	}
 	else
 	{
-		P_MorphMonster (target, TypeInfo::FindType ("Pig"));
+		P_MorphMonster (target, PClass::FindClass (NAME_Pig));
 	}
 	return -1;
 }
diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp
index 68e735890..6c1f1c6fc 100644
--- a/src/g_raven/a_minotaur.cpp
+++ b/src/g_raven/a_minotaur.cpp
@@ -588,15 +588,15 @@ void A_MinotaurCharge (AActor *actor)
 
 	if (actor->special1 > 0)
 	{
-		const TypeInfo *type;
+		const PClass *type;
 
 		if (gameinfo.gametype == GAME_Heretic)
 		{
-			type = TypeInfo::FindType ("PhoenixPuff");
+			type = PClass::FindClass ("PhoenixPuff");
 		}
 		else
 		{
-			type = TypeInfo::FindType ("PunchPuff");
+			type = PClass::FindClass ("PunchPuff");
 		}
 		puff = Spawn (type, actor->x, actor->y, actor->z);
 		puff->momz = 2*FRACUNIT;
diff --git a/src/g_raven/ravenshared.h b/src/g_raven/ravenshared.h
index 8aa35dd5f..0a4250f58 100644
--- a/src/g_raven/ravenshared.h
+++ b/src/g_raven/ravenshared.h
@@ -7,7 +7,7 @@ class player_s;
 bool P_MorphPlayer (player_s *player);
 bool P_UndoPlayerMorph (player_s *player, bool force);
 
-bool P_MorphMonster (AActor *actor, const TypeInfo *morphClass);
+bool P_MorphMonster (AActor *actor, const PClass *morphClass);
 bool P_UpdateMorphedMonster (AActor *actor, int tics);
 
 class AMinotaur : public AActor
diff --git a/src/g_shared/a_artifacts.h b/src/g_shared/a_artifacts.h
index 24c6b6e49..cabaacf71 100644
--- a/src/g_shared/a_artifacts.h
+++ b/src/g_shared/a_artifacts.h
@@ -50,7 +50,7 @@ public:
 	virtual bool Use (bool pickup);
 	virtual void Serialize (FArchive &arc);
 
-	const TypeInfo *PowerupType;
+	const PClass *PowerupType;
 	int EffectTics;			// Non-0 to override the powerup's default tics
 	PalEntry BlendColor;	// Non-0 to override the powerup's default blend
 };
diff --git a/src/g_shared/a_debris.cpp b/src/g_shared/a_debris.cpp
index 2a7550d25..3d4b7f433 100644
--- a/src/g_shared/a_debris.cpp
+++ b/src/g_shared/a_debris.cpp
@@ -31,7 +31,7 @@ IMPLEMENT_ABSTRACT_ACTOR(AGlassShard)
 void P_SpawnDirt (AActor *actor, fixed_t radius)
 {
 	fixed_t x,y,z;
-	const TypeInfo *dtype = NULL;
+	const PClass *dtype = NULL;
 	AActor *mo;
 	angle_t angle;
 
@@ -42,7 +42,7 @@ void P_SpawnDirt (AActor *actor, fixed_t radius)
 
 	char fmt[8];
 	sprintf(fmt, "Dirt%d", 1 + pr_dirt()%6);
-	dtype = TypeInfo::FindType(fmt);
+	dtype = PClass::FindClass(fmt);
 	if (dtype)
 	{
 		mo = Spawn (dtype, x, y, z);
diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp
index 8af3e0d70..6eaf654c9 100644
--- a/src/g_shared/a_keys.cpp
+++ b/src/g_shared/a_keys.cpp
@@ -13,7 +13,7 @@
 
 struct OneKey
 {
-	const TypeInfo * key;
+	const PClass * key;
 	int count;
 
 	bool check(AActor * owner)
@@ -109,7 +109,7 @@ static const char * keywords_lock[]={
 //
 //===========================================================================
 
-static void AddOneKey(Keygroup * keygroup, const TypeInfo * mi)
+static void AddOneKey(Keygroup * keygroup, const PClass * mi)
 {
 	if (mi)
 	{
@@ -149,14 +149,14 @@ static void AddOneKey(Keygroup * keygroup, const TypeInfo * mi)
 static Keygroup * ParseKeygroup()
 {
 	Keygroup * keygroup;
-	const TypeInfo * mi;
+	const PClass * mi;
 
 	SC_MustGetStringName("{");
 	keygroup=new Keygroup;
 	while (!SC_CheckString("}"))
 	{
 		SC_MustGetString();
-		mi=TypeInfo::FindType(sc_String);
+		mi=PClass::FindClass(sc_String);
 		AddOneKey(keygroup, mi);
 	}
 	if (keygroup->anykeylist.Size()==0)
@@ -213,7 +213,7 @@ static void ParseLock()
 	Lock sink;
 	Lock * lock=&sink;
 	Keygroup * keygroup;
-	const TypeInfo * mi;
+	const PClass * mi;
 
 	SC_MustGetNumber();
 	keynum=sc_Number;
@@ -288,7 +288,7 @@ static void ParseLock()
 			break;
 
 		default:
-			mi=TypeInfo::FindType(sc_String);
+			mi=PClass::FindClass(sc_String);
 			if (mi) 
 			{
 				keygroup=new Keygroup;
@@ -318,12 +318,11 @@ static void ParseLock()
 static void ClearLocks()
 {
 	int i;
-	for(i=0;i<TypeInfo::m_Types.Size();i++)
+	for(i=0;i<PClass::m_Types.Size();i++)
 	{
-		if (TypeInfo::m_Types[i]->IsDescendantOf(RUNTIME_CLASS(AKey)))
+		if (PClass::m_Types[i]->IsDescendantOf(RUNTIME_CLASS(AKey)))
 		{
-			if (TypeInfo::m_Types[i]->ActorInfo != NULL)
-				static_cast<AKey*>(GetDefaultByType(TypeInfo::m_Types[i]))->KeyNumber=0;
+			static_cast<AKey*>(GetDefaultByType(PClass::m_Types[i]))->KeyNumber=0;
 		}
 	}
 	for(i=0;i<256;i++)
diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp
index 57d233fe6..d81cd417d 100644
--- a/src/g_shared/a_pickups.cpp
+++ b/src/g_shared/a_pickups.cpp
@@ -49,13 +49,13 @@ void AAmmo::Serialize (FArchive &arc)
 //
 //===========================================================================
 
-const TypeInfo *AAmmo::GetParentAmmo () const
+const PClass *AAmmo::GetParentAmmo () const
 {
-	const TypeInfo *type = GetClass ();
+	const PClass *type = GetClass ();
 
-	while (type->ParentType != RUNTIME_CLASS(AAmmo))
+	while (type->ParentClass != RUNTIME_CLASS(AAmmo))
 	{
-		type = type->ParentType;
+		type = type->ParentClass;
 	}
 	return type;
 }
@@ -140,9 +140,9 @@ AInventory *AAmmo::CreateCopy (AActor *other)
 			amount += amount >> 1;
 	}
 
-	if (GetClass()->ParentType != RUNTIME_CLASS(AAmmo))
+	if (GetClass()->ParentClass != RUNTIME_CLASS(AAmmo))
 	{
-		const TypeInfo *type = GetParentAmmo();
+		const PClass *type = GetParentAmmo();
 		if (!GoAway ())
 		{
 			Destroy ();
@@ -1208,7 +1208,9 @@ CCMD (printinv)
 	}
 	for (item = players[consoleplayer].mo->Inventory; item != NULL; item = item->Inventory)
 	{
-		Printf ("%s #%lu (%d/%d)\n", item->GetClass()->Name+1, item->InventoryID, item->Amount, item->MaxAmount);
+		Printf ("%s #%lu (%d/%d)\n", item->GetClass()->TypeName.GetChars(),
+			item->InventoryID,
+			item->Amount, item->MaxAmount);
 	}
 }
 
@@ -1912,11 +1914,11 @@ AInventory *ABackpack::CreateCopy (AActor *other)
 {
 	// Find every unique type of ammo. Give it to the player if
 	// he doesn't have it already, and double it's maximum capacity.
-	for (unsigned int i = 0; i < TypeInfo::m_Types.Size(); ++i)
+	for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
 	{
-		const TypeInfo *type = TypeInfo::m_Types[i];
+		const PClass *type = PClass::m_Types[i];
 
-		if (type->ParentType == RUNTIME_CLASS(AAmmo) &&
+		if (type->ParentClass == RUNTIME_CLASS(AAmmo) &&
 			((AAmmo *)GetDefaultByType (type))->BackpackAmount > 0)
 		{
 			AAmmo *ammo = static_cast<AAmmo *>(other->FindInventory (type));
@@ -1959,13 +1961,13 @@ bool ABackpack::HandlePickup (AInventory *item)
 {
 	// Since you already have a backpack, that means you already have every
 	// kind of ammo in your inventory, so we don't need to look at the
-	// entire TypeInfo list to discover what kinds of ammo exist, and we don't
+	// entire PClass list to discover what kinds of ammo exist, and we don't
 	// have to alter the MaxAmount either.
 	if (item->IsKindOf (RUNTIME_CLASS(ABackpack)))
 	{
 		for (AInventory *probe = Owner->Inventory; probe != NULL; probe = probe->Inventory)
 		{
-			if (probe->GetClass()->ParentType == RUNTIME_CLASS(AAmmo))
+			if (probe->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo))
 			{
 				if (probe->Amount < probe->MaxAmount)
 				{
@@ -2020,7 +2022,7 @@ void ABackpack::DetachFromOwner ()
 
 	for (item = Owner->Inventory; item != NULL; item = item->Inventory)
 	{
-		if (item->GetClass()->ParentType == RUNTIME_CLASS(AAmmo) &&
+		if (item->GetClass()->ParentClass == RUNTIME_CLASS(AAmmo) &&
 			item->MaxAmount == static_cast<AAmmo*>(item)->BackpackMaxAmount)
 		{
 			item->MaxAmount = static_cast<AInventory*>(item->GetDefault())->MaxAmount;
diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h
index 5c2021877..963cd0612 100644
--- a/src/g_shared/a_pickups.h
+++ b/src/g_shared/a_pickups.h
@@ -20,11 +20,11 @@ public:
 	FWeaponSlot ();
 	void Clear ();
 	bool AddWeapon (const char *type);
-	bool AddWeapon (const TypeInfo *type);
+	bool AddWeapon (const PClass *type);
 	AWeapon *PickWeapon (player_s *player);
 	int CountWeapons ();
 
-	inline const TypeInfo *GetWeapon (int index) const
+	inline const PClass *GetWeapon (int index) const
 	{
 		return Weapons[index];
 	}
@@ -35,7 +35,7 @@ public:
 	friend struct FWeaponSlots;
 
 private:
-	const TypeInfo *Weapons[MAX_WEAPONS_PER_SLOT];
+	const PClass *Weapons[MAX_WEAPONS_PER_SLOT];
 };
 
 // FWeaponSlots::AddDefaultWeapon return codes
@@ -51,8 +51,8 @@ struct FWeaponSlots
 	FWeaponSlot Slots[NUM_WEAPON_SLOTS];
 
 	void Clear ();
-	bool LocateWeapon (const TypeInfo *type, int *const slot, int *const index);
-	ESlotDef AddDefaultWeapon (int slot, const TypeInfo *type);
+	bool LocateWeapon (const PClass *type, int *const slot, int *const index);
+	ESlotDef AddDefaultWeapon (int slot, const PClass *type);
 	int RestoreSlots (FConfigFile &config);
 	void SaveSlots (FConfigFile &config);
 };
@@ -178,7 +178,7 @@ public:
 	void Serialize (FArchive &arc);
 	AInventory *CreateCopy (AActor *other);
 	bool HandlePickup (AInventory *item);
-	const TypeInfo *GetParentAmmo () const;
+	const PClass *GetParentAmmo () const;
 
 	int BackpackAmount, BackpackMaxAmount;
 };
@@ -190,16 +190,16 @@ class AWeapon : public AInventory
 	HAS_OBJECT_POINTERS
 public:
 	DWORD WeaponFlags;
-	const TypeInfo *AmmoType1, *AmmoType2;	// Types of ammo used by this weapon
+	const PClass *AmmoType1, *AmmoType2;	// Types of ammo used by this weapon
 	int AmmoGive1, AmmoGive2;				// Amount of each ammo to get when picking up weapon
 	int MinAmmo1, MinAmmo2;					// Minimum ammo needed to switch to this weapon
 	int AmmoUse1, AmmoUse2;					// How much ammo to use with each shot
 	int Kickback;
 	fixed_t YAdjust;						// For viewing the weapon fullscreen
 	WORD UpSound, ReadySound;				// Sounds when coming up and idle
-	const TypeInfo *SisterWeaponType;		// Another weapon to pick up with this one
-	const TypeInfo *ProjectileType;			// Projectile used by primary attack
-	const TypeInfo *AltProjectileType;		// Projectile used by alternate attack
+	const PClass *SisterWeaponType;		// Another weapon to pick up with this one
+	const PClass *ProjectileType;			// Projectile used by primary attack
+	const PClass *AltProjectileType;		// Projectile used by alternate attack
 	int SelectionOrder;						// Lower-numbered weapons get picked first
 	fixed_t MoveCombatDist;					// Used by bots, but do they *really* need it?
 
@@ -245,9 +245,9 @@ public:
 	bool DepleteAmmo (bool altFire, bool checkEnough=true);
 
 protected:
-	static AAmmo *AddAmmo (AActor *other, const TypeInfo *ammotype, int amount);
+	static AAmmo *AddAmmo (AActor *other, const PClass *ammotype, int amount);
 	static bool AddExistingAmmo (AAmmo *ammo, int amount);
-	AWeapon *AddWeapon (const TypeInfo *weapon);
+	AWeapon *AddWeapon (const PClass *weapon);
 };
 
 enum
diff --git a/src/g_shared/a_weaponpiece.cpp b/src/g_shared/a_weaponpiece.cpp
index 14b76f76a..c7a3318cf 100644
--- a/src/g_shared/a_weaponpiece.cpp
+++ b/src/g_shared/a_weaponpiece.cpp
@@ -11,7 +11,7 @@ class AWeaponHolder : public AInventory
 
 public:
 	int PieceMask;
-	const TypeInfo * PieceWeapon;
+	const PClass * PieceWeapon;
 
 	void Serialize (FArchive &arc)
 	{
diff --git a/src/g_shared/a_weaponpiece.h b/src/g_shared/a_weaponpiece.h
index 1836f89f8..f0d465771 100644
--- a/src/g_shared/a_weaponpiece.h
+++ b/src/g_shared/a_weaponpiece.h
@@ -12,6 +12,6 @@ public:
 	virtual void PlayPickupSound (AActor *toucher);
 
 	int PieceValue;
-	const TypeInfo * WeaponClass;
+	const PClass * WeaponClass;
 	AWeapon * FullWeapon;
 };
diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp
index 8714ad5fc..3017546eb 100644
--- a/src/g_shared/a_weapons.cpp
+++ b/src/g_shared/a_weapons.cpp
@@ -242,7 +242,7 @@ void AWeapon::AttachToOwner (AActor *other)
 //
 //===========================================================================
 
-AAmmo *AWeapon::AddAmmo (AActor *other, const TypeInfo *ammotype, int amount)
+AAmmo *AWeapon::AddAmmo (AActor *other, const PClass *ammotype, int amount)
 {
 	AAmmo *ammo;
 
@@ -298,7 +298,7 @@ bool AWeapon::AddExistingAmmo (AAmmo *ammo, int amount)
 //
 //===========================================================================
 
-AWeapon *AWeapon::AddWeapon (const TypeInfo *weapontype)
+AWeapon *AWeapon::AddWeapon (const PClass *weapontype)
 {
 	AWeapon *weap;
 
@@ -555,10 +555,10 @@ void FWeaponSlot::Clear ()
 
 bool FWeaponSlot::AddWeapon (const char *type)
 {
-	return AddWeapon (TypeInfo::IFindType (type));
+	return AddWeapon (PClass::FindClass (type));
 }
 
-bool FWeaponSlot::AddWeapon (const TypeInfo *type)
+bool FWeaponSlot::AddWeapon (const PClass *type)
 {
 	int i;
 
@@ -628,7 +628,7 @@ void FWeaponSlots::Clear ()
 // then add it to the specified slot. False is returned if the weapon was
 // not in a slot and could not be added. True is returned otherwise.
 
-ESlotDef FWeaponSlots::AddDefaultWeapon (int slot, const TypeInfo *type)
+ESlotDef FWeaponSlots::AddDefaultWeapon (int slot, const PClass *type)
 {
 	int currSlot, index;
 
@@ -644,7 +644,7 @@ ESlotDef FWeaponSlots::AddDefaultWeapon (int slot, const TypeInfo *type)
 	return SLOTDEF_Exists;
 }
 
-bool FWeaponSlots::LocateWeapon (const TypeInfo *type, int *const slot, int *const index)
+bool FWeaponSlots::LocateWeapon (const PClass *type, int *const slot, int *const index)
 {
 	int i, j;
 
@@ -724,7 +724,7 @@ AWeapon *PickNextWeapon (player_s *player)
 		{
 			int slot = (unsigned)((start + i) / MAX_WEAPONS_PER_SLOT) % NUM_WEAPON_SLOTS;
 			int index = (unsigned)(start + i) % MAX_WEAPONS_PER_SLOT;
-			const TypeInfo *type = LocalWeapons.Slots[slot].Weapons[index];
+			const PClass *type = LocalWeapons.Slots[slot].Weapons[index];
 			AWeapon *weap = static_cast<AWeapon *> (player->mo->FindInventory (type));
 
 			if (weap != NULL && weap->CheckAmmo (AWeapon::EitherFire, false))
@@ -759,7 +759,7 @@ AWeapon *PickPrevWeapon (player_s *player)
 				slot += NUM_WEAPON_SLOTS * MAX_WEAPONS_PER_SLOT;
 			int index = slot % MAX_WEAPONS_PER_SLOT;
 			slot /= MAX_WEAPONS_PER_SLOT;
-			const TypeInfo *type = LocalWeapons.Slots[slot].Weapons[index];
+			const PClass *type = LocalWeapons.Slots[slot].Weapons[index];
 			AWeapon *weap = static_cast<AWeapon *> (player->mo->FindInventory (type));
 
 			if (weap != NULL && weap->CheckAmmo (AWeapon::EitherFire, false))
@@ -791,7 +791,7 @@ CCMD (setslot)
 				i < MAX_WEAPONS_PER_SLOT && LocalWeapons.Slots[slot].GetWeapon(i) != NULL;
 				++i)
 			{
-				Printf (" %s", LocalWeapons.Slots[slot].GetWeapon(i)->Name+1);
+				Printf (" %s", LocalWeapons.Slots[slot].GetWeapon(i)->TypeName.GetChars());
 			}
 			Printf ("\n");
 		}
@@ -881,7 +881,7 @@ CCMD (weaponsection)
 
 CCMD (addslotdefault)
 {
-	const TypeInfo *type;
+	const PClass *type;
 	unsigned int slot;
 
 	if (argv.argc() != 3 || (slot = atoi (argv[1])) >= NUM_WEAPON_SLOTS)
@@ -896,7 +896,7 @@ CCMD (addslotdefault)
 		return;
 	}
 
-	type = TypeInfo::IFindType (argv[2]);
+	type = PClass::FindClass (argv[2]);
 	if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
 	{
 		Printf ("%s is not a weapon\n", argv[2]);
@@ -975,7 +975,7 @@ void FWeaponSlots::SaveSlots (FConfigFile &config)
 			{
 				buff[index++] = ' ';
 			}
-			const char *name = Slots[i].Weapons[j]->Name+1;
+			const char *name = Slots[i].Weapons[j]->TypeName.GetChars();
 			strcpy (buff+index, name);
 			index += (int)strlen (name);
 		}
diff --git a/src/g_shared/sbar.h b/src/g_shared/sbar.h
index ff5b7ab87..aae2c44b6 100644
--- a/src/g_shared/sbar.h
+++ b/src/g_shared/sbar.h
@@ -182,7 +182,7 @@ public:
 	virtual void Tick ();
 	virtual void Draw (EHudState state);
 			void DrawTopStuff (EHudState state);
-	virtual void FlashItem (const TypeInfo *itemtype);
+	virtual void FlashItem (const PClass *itemtype);
 	virtual void AttachToPlayer (player_s *player);
 	virtual void FlashCrosshair ();
 	virtual void BlendView (float blend[4]);
diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp
index 6210fbecb..930f0b03b 100644
--- a/src/g_shared/shared_sbar.cpp
+++ b/src/g_shared/shared_sbar.cpp
@@ -1427,7 +1427,7 @@ void FBaseStatusBar::DrawConsistancy () const
 	}
 }
 
-void FBaseStatusBar::FlashItem (const TypeInfo *itemtype)
+void FBaseStatusBar::FlashItem (const PClass *itemtype)
 {
 }
 
diff --git a/src/g_strife/a_alienspectres.cpp b/src/g_strife/a_alienspectres.cpp
index 44af66a61..cf511cd14 100644
--- a/src/g_strife/a_alienspectres.cpp
+++ b/src/g_strife/a_alienspectres.cpp
@@ -26,7 +26,7 @@ void A_AlienSpectreDeath (AActor *);
 void A_AlertMonsters (AActor *);
 void A_Tracer2 (AActor *);
 
-AActor *P_SpawnSubMissile (AActor *source, TypeInfo *type, AActor *target);
+AActor *P_SpawnSubMissile (AActor *source, PClass *type, AActor *target);
 
 // Alien Spectre 1 -----------------------------------------------------------
 
@@ -340,7 +340,7 @@ END_DEFAULTS
 
 //============================================================================
 
-static void GenericSpectreSpawn (AActor *actor, const TypeInfo *type)
+static void GenericSpectreSpawn (AActor *actor, const PClass *type)
 {
 	AActor *spectre = Spawn (type, actor->x, actor->y, actor->z);
 	if (spectre != NULL)
diff --git a/src/g_strife/a_strifeglobal.h b/src/g_strife/a_strifeglobal.h
index c9c15e532..6d150d2b9 100644
--- a/src/g_strife/a_strifeglobal.h
+++ b/src/g_strife/a_strifeglobal.h
@@ -108,7 +108,7 @@ public:
 	int NumPieces, DownPieces;
 };
 
-extern const TypeInfo *QuestItemClasses[31];
+extern const PClass *QuestItemClasses[31];
 
 // Sigil/Spectral projectiles -----------------------------------------------
 
diff --git a/src/g_strife/a_strifeplayer.cpp b/src/g_strife/a_strifeplayer.cpp
index e7a212c8c..e073decee 100644
--- a/src/g_strife/a_strifeplayer.cpp
+++ b/src/g_strife/a_strifeplayer.cpp
@@ -137,7 +137,7 @@ void AStrifePlayer::GiveDefaultInventory ()
 	AWeapon *weapon;
 
 	player->health = GetDefault()->health;
-	weapon = static_cast<AWeapon *>(player->mo->GiveInventoryType (TypeInfo::FindType ("PunchDagger")));
+	weapon = static_cast<AWeapon *>(player->mo->GiveInventoryType (PClass::FindClass ("PunchDagger")));
 	player->ReadyWeapon = player->PendingWeapon = weapon;
 }
 
diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp
index c562bb14b..0a3ecb4f7 100644
--- a/src/g_strife/a_strifestuff.cpp
+++ b/src/g_strife/a_strifestuff.cpp
@@ -767,7 +767,7 @@ END_DEFAULTS
 
 void A_TossGib (AActor *self)
 {
-	const TypeInfo *gibtype = (self->flags & MF_NOBLOOD) ? RUNTIME_CLASS(AJunk) : RUNTIME_CLASS(AMeat);
+	const PClass *gibtype = (self->flags & MF_NOBLOOD) ? RUNTIME_CLASS(AJunk) : RUNTIME_CLASS(AMeat);
 	AActor *gib = Spawn (gibtype, self->x, self->y, self->z + 24*FRACUNIT);
 	angle_t an;
 	int speed;
diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp
index 73f991639..88c4682a6 100644
--- a/src/g_strife/a_strifeweapons.cpp
+++ b/src/g_strife/a_strifeweapons.cpp
@@ -1419,7 +1419,7 @@ void A_FireMauler2 (AActor *self)
 //
 //============================================================================
 
-AActor *P_SpawnSubMissile (AActor *source, TypeInfo *type, AActor *target);
+AActor *P_SpawnSubMissile (AActor *source, PClass *type, AActor *target);
 
 void A_MaulerTorpedoWave (AActor *self)
 {
@@ -1441,7 +1441,7 @@ void A_MaulerTorpedoWave (AActor *self)
 	self->z = savedz;
 }
 
-AActor *P_SpawnSubMissile (AActor *source, TypeInfo *type, AActor *target)
+AActor *P_SpawnSubMissile (AActor *source, PClass *type, AActor *target)
 {
 	AActor *other = Spawn (type, source->x, source->y, source->z);
 
@@ -1812,7 +1812,7 @@ END_DEFAULTS
 
 void A_FireGrenade (AActor *self)
 {
-	TypeInfo *grenadetype;
+	PClass *grenadetype;
 	player_t *player = self->player;
 	AActor *grenade;
 	angle_t an;
@@ -2458,7 +2458,7 @@ int ASigil::GiveSigilPiece (AActor *receiver)
 	else if (sigil->NumPieces < 5)
 	{
 		++sigil->NumPieces;
-		static const TypeInfo *const sigils[5] =
+		static const PClass *const sigils[5] =
 		{
 			RUNTIME_CLASS(ASigil1),
 			RUNTIME_CLASS(ASigil2),
diff --git a/src/g_strife/a_thingstoblowup.cpp b/src/g_strife/a_thingstoblowup.cpp
index 87e2641dd..b2212162f 100644
--- a/src/g_strife/a_thingstoblowup.cpp
+++ b/src/g_strife/a_thingstoblowup.cpp
@@ -9,7 +9,7 @@
 static FRandom pr_bang4cloud ("Bang4Cloud");
 static FRandom pr_lightout ("LightOut");
 
-extern const TypeInfo *QuestItemClasses[31];
+extern const PClass *QuestItemClasses[31];
 
 void A_TossGib (AActor *);
 void A_LoopActiveSound (AActor *);
diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp
index 63b68e3b1..1004c1edc 100644
--- a/src/g_strife/strife_sbar.cpp
+++ b/src/g_strife/strife_sbar.cpp
@@ -358,7 +358,7 @@ private:
 		}
 	}
 
-	void FlashItem (const TypeInfo *itemtype)
+	void FlashItem (const PClass *itemtype)
 	{
 		ItemFlash = FRACUNIT*3/4;
 	}
@@ -628,7 +628,7 @@ private:
 				label = item->GetClass()->Meta.GetMetaString (AMETA_StrifeName);
 				if (label == NULL)
 				{
-					label = item->GetClass()->Name + 1;
+					label = item->GetClass()->TypeName.GetChars();
 				}
 
 				int colnum = ((i-pos) / 5) & (KeyPopScroll > 0 ? 3 : 1);
@@ -685,7 +685,7 @@ private:
 			// How much ammo does the player have?
 			static const struct
 			{
-				const TypeInfo *AmmoType;
+				const PClass *AmmoType;
 				int Y;
 			} AmmoList[7] =
 			{
@@ -717,20 +717,20 @@ private:
 			// What weapons does the player have?
 			static const struct
 			{
-				const char *TypeName;
+				ENamedName TypeName;
 				int X, Y;
 			} WeaponList[6] =
 			{
-				{ "StrifeCrossbow",			23, 19 },
-				{ "AssaultGun",				21, 41 },
-				{ "FlameThrower",			57, 50 },
-				{ "MiniMissileLauncher",	20, 64 },
-				{ "StrifeGrenadeLauncher",	55, 20 },
-				{ "Mauler",					52, 75 },
+				{ NAME_StrifeCrossbow,			23, 19 },
+				{ NAME_AssaultGun,				21, 41 },
+				{ NAME_FlameThrower,			57, 50 },
+				{ NAME_MiniMissileLauncher,		20, 64 },
+				{ NAME_StrifeGrenadeLauncher,	55, 20 },
+				{ NAME_Mauler,					52, 75 },
 			};
 			for (i = 0; i < 6; ++i)
 			{
-				item = CPlayer->mo->FindInventory (TypeInfo::FindType (WeaponList[i].TypeName));
+				item = CPlayer->mo->FindInventory (PClass::FindClass (WeaponList[i].TypeName));
 
 				if (item != NULL)
 				{
diff --git a/src/info.cpp b/src/info.cpp
index eedb2f60a..90b30281f 100644
--- a/src/info.cpp
+++ b/src/info.cpp
@@ -66,7 +66,7 @@ extern void LoadDecorations (void (*process)(FState *, int));
 
 FArchive &operator<< (FArchive &arc, FState *&state)
 {
-	const TypeInfo *info;
+	const PClass *info;
 
 	if (arc.IsStoring ())
 	{
@@ -91,7 +91,7 @@ FArchive &operator<< (FArchive &arc, FState *&state)
 	}
 	else
 	{
-		const TypeInfo *info;
+		const PClass *info;
 		DWORD ofs;
 
 		arc.UserReadClass (info);
@@ -113,7 +113,7 @@ FArchive &operator<< (FArchive &arc, FState *&state)
 }
 
 // Find the actor that a state belongs to.
-const TypeInfo *FState::StaticFindStateOwner (const FState *state)
+const PClass *FState::StaticFindStateOwner (const FState *state)
 {
 	const FActorInfo *info = RUNTIME_CLASS(AActor)->ActorInfo;
 
@@ -133,9 +133,9 @@ const TypeInfo *FState::StaticFindStateOwner (const FState *state)
 		}
 	}
 
-	for (unsigned int i = 0; i < TypeInfo::m_RuntimeActors.Size(); ++i)
+	for (unsigned int i = 0; i < PClass::m_RuntimeActors.Size(); ++i)
 	{
-		info = TypeInfo::m_RuntimeActors[i]->ActorInfo;
+		info = PClass::m_RuntimeActors[i]->ActorInfo;
 		if (state >= info->OwnedStates &&
 			state <  info->OwnedStates + info->NumOwnedStates)
 		{
@@ -148,7 +148,7 @@ const TypeInfo *FState::StaticFindStateOwner (const FState *state)
 
 // Find the actor that a state belongs to, but restrict the search to
 // the specified type and its ancestors.
-const TypeInfo *FState::StaticFindStateOwner (const FState *state, const FActorInfo *info)
+const PClass *FState::StaticFindStateOwner (const FState *state, const FActorInfo *info)
 {
 	while (info != NULL)
 	{
@@ -157,7 +157,7 @@ const TypeInfo *FState::StaticFindStateOwner (const FState *state, const FActorI
 		{
 			return info->Class;
 		}
-		info = info->Class->ParentType->ActorInfo;
+		info = info->Class->ParentClass->ActorInfo;
 	}
 	return NULL;
 }
@@ -218,7 +218,7 @@ void FActorInfo::StaticInit ()
 		sprites.Push (temp);
 	}
 
-	// Attach FActorInfo structures to every actor's TypeInfo
+	// Attach FActorInfo structures to every actor's PClass
 	while (++reg != NULL)
 	{
 		reg->Class->ActorInfo = reg;
@@ -226,7 +226,7 @@ void FActorInfo::StaticInit ()
 			(unsigned)reg->OwnedStates->sprite.index < sprites.Size ())
 		{
 			Printf ("\x1c+%s is stateless. Fix its default list.\n",
-				reg->Class->Name + 1);
+				reg->Class->TypeName.GetChars());
 		}
 		ProcessStates (reg->OwnedStates, reg->NumOwnedStates);
 	}
@@ -266,9 +266,9 @@ void FActorInfo::StaticSetActorNums ()
 		reg->RegisterIDs ();
 	}
 
-	for (unsigned int i = 0; i < TypeInfo::m_RuntimeActors.Size(); ++i)
+	for (unsigned int i = 0; i < PClass::m_RuntimeActors.Size(); ++i)
 	{
-		TypeInfo::m_RuntimeActors[i]->ActorInfo->RegisterIDs ();
+		PClass::m_RuntimeActors[i]->ActorInfo->RegisterIDs ();
 	}
 }
 
@@ -308,7 +308,7 @@ FDoomEdMap::~FDoomEdMap()
 	Empty();
 }
 
-void FDoomEdMap::AddType (int doomednum, const TypeInfo *type)
+void FDoomEdMap::AddType (int doomednum, const PClass *type)
 {
 	unsigned int hash = (unsigned int)doomednum % DOOMED_HASHSIZE;
 	FDoomEdEntry *entry = DoomEdHash[hash];
@@ -326,7 +326,7 @@ void FDoomEdMap::AddType (int doomednum, const TypeInfo *type)
 	else
 	{
 		Printf (PRINT_BOLD, "Warning: %s and %s both have doomednum %d.\n",
-			type->Name+1, entry->Type->Name+1, doomednum);
+			type->TypeName.GetChars(), entry->Type->TypeName.GetChars(), doomednum);
 	}
 	entry->Type = type;
 }
@@ -366,7 +366,7 @@ void FDoomEdMap::Empty ()
 	}
 }
 
-const TypeInfo *FDoomEdMap::FindType (int doomednum) const
+const PClass *FDoomEdMap::FindType (int doomednum) const
 {
 	unsigned int hash = (unsigned int)doomednum % DOOMED_HASHSIZE;
 	FDoomEdEntry *entry = DoomEdHash[hash];
@@ -377,7 +377,7 @@ const TypeInfo *FDoomEdMap::FindType (int doomednum) const
 
 struct EdSorting
 {
-	const TypeInfo *Type;
+	const PClass *Type;
 	int DoomEdNum;
 };
 
@@ -389,7 +389,7 @@ static int STACK_ARGS sortnums (const void *a, const void *b)
 
 void FDoomEdMap::DumpMapThings ()
 {
-	TArray<EdSorting> infos (TypeInfo::m_Types.Size());
+	TArray<EdSorting> infos (PClass::m_Types.Size());
 	int i;
 
 	for (i = 0; i < DOOMED_HASHSIZE; ++i)
@@ -415,7 +415,7 @@ void FDoomEdMap::DumpMapThings ()
 		for (i = 0; i < (int)infos.Size (); ++i)
 		{
 			Printf ("%6d %s\n",
-				infos[i].DoomEdNum, infos[i].Type->Name + 1);
+				infos[i].DoomEdNum, infos[i].Type->TypeName.GetChars());
 		}
 	}
 }
@@ -434,15 +434,14 @@ CCMD (summon)
 
 	if (argv.argc() > 1)
 	{
-		// Don't use FindType, because we want a case-insensitive search
-		const TypeInfo *type = TypeInfo::IFindType (argv[1]);
+		const PClass *type = PClass::FindClass (argv[1]);
 		if (type == NULL)
 		{
 			Printf ("Unknown class '%s'\n", argv[1]);
 			return;
 		}
 		Net_WriteByte (DEM_SUMMON);
-		Net_WriteString (type->Name + 1);
+		Net_WriteString (type->TypeName.GetChars());
 	}
 }
 
@@ -453,14 +452,13 @@ CCMD (summonfriend)
 
 	if (argv.argc() > 1)
 	{
-		// Don't use FindType, because we want a case-insensitive search
-		const TypeInfo *type = TypeInfo::IFindType (argv[1]);
+		const PClass *type = PClass::FindClass (argv[1]);
 		if (type == NULL)
 		{
 			Printf ("Unknown class '%s'\n", argv[1]);
 			return;
 		}
 		Net_WriteByte (DEM_SUMMONFRIEND);
-		Net_WriteString (type->Name + 1);
+		Net_WriteString (type->TypeName.GetChars());
 	}
 }
diff --git a/src/info.h b/src/info.h
index c6fb60d51..6db5982f7 100644
--- a/src/info.h
+++ b/src/info.h
@@ -162,8 +162,8 @@ struct FState
 		Frame = (Frame & (SF_FULLBRIGHT|SF_BIGTIC)) | (frame-'A');
 	}
 
-	static const TypeInfo *StaticFindStateOwner (const FState *state);
-	static const TypeInfo *StaticFindStateOwner (const FState *state, const FActorInfo *info);
+	static const PClass *StaticFindStateOwner (const FState *state);
+	static const PClass *StaticFindStateOwner (const FState *state, const FActorInfo *info);
 };
 
 // A truly awful hack to get to the state that called an action function
@@ -369,9 +369,8 @@ struct FActorInfo
 	void ApplyDefaults (BYTE *defaults);
 	void RegisterIDs ();
 
-	TypeInfo *Class;
+	PClass *Class;
 	FState *OwnedStates;
-	BYTE *Defaults;
 	int NumOwnedStates;
 	BYTE GameFilter;
 	BYTE SpawnID;
@@ -395,8 +394,8 @@ class FDoomEdMap
 public:
 	~FDoomEdMap();
 
-	const TypeInfo *FindType (int doomednum) const;
-	void AddType (int doomednum, const TypeInfo *type);
+	const PClass *FindType (int doomednum) const;
+	void AddType (int doomednum, const PClass *type);
 	void DelType (int doomednum);
 	void Empty ();
 
@@ -408,7 +407,7 @@ private:
 	struct FDoomEdEntry
 	{
 		FDoomEdEntry *HashNext;
-		const TypeInfo *Type;
+		const PClass *Type;
 		int DoomEdNum;
 	};
 
diff --git a/src/infodefaults.cpp b/src/infodefaults.cpp
index 79f48833f..732d8bcd4 100644
--- a/src/infodefaults.cpp
+++ b/src/infodefaults.cpp
@@ -48,37 +48,37 @@
 
 void FActorInfo::BuildDefaults ()
 {
-	if (Defaults == NULL)
+	if (Class->Defaults == NULL)
 	{
-		Defaults = new BYTE[Class->SizeOf];
+		Class->Defaults = new BYTE[Class->Size];
 		if (Class == RUNTIME_CLASS(AActor))
 		{
-			memset (Defaults, 0, Class->SizeOf);
+			memset (Class->Defaults, 0, Class->Size);
 		}
 		else
 		{
-			TypeInfo *parent;
+			PClass *parent;
 
-			parent = Class->ParentType;
+			parent = Class->ParentClass;
 			parent->ActorInfo->BuildDefaults ();
-			assert (Class->SizeOf >= parent->SizeOf);
-			memcpy (Defaults, parent->ActorInfo->Defaults, parent->SizeOf);
-			if (Class->SizeOf > parent->SizeOf)
+			assert (Class->Size >= parent->Size);
+			memcpy (Class->Defaults, parent->Defaults, parent->Size);
+			if (Class->Size > parent->Size)
 			{
-				memset (Defaults + parent->SizeOf, 0, Class->SizeOf - parent->SizeOf);
+				memset (Class->Defaults + parent->Size, 0, Class->Size - parent->Size);
 			}
 			if (parent == RUNTIME_CLASS(AActor) && OwnedStates == NULL)
 			{ // Stateless actors that are direct subclasses of AActor
 			  // have their spawnstate default to something that won't
 			  // immediately destroy them.
-				((AActor *)(Defaults))->SpawnState = &AActor::States[0];
+				((AActor *)(Class->Defaults))->SpawnState = &AActor::States[0];
 			}
 		}
-		ApplyDefaults (Defaults);
+		ApplyDefaults (Class->Defaults);
 	}
 }
 
-static FState *DefaultStates (TypeInfo *type)
+static FState *DefaultStates (PClass *type)
 {
 	FState *states = type->ActorInfo->OwnedStates;
 
@@ -86,21 +86,21 @@ static FState *DefaultStates (TypeInfo *type)
 	{
 		do
 		{
-			type = type->ParentType;
+			type = type->ParentClass;
 			states = type->ActorInfo->OwnedStates;
 		} while (states == NULL && type != RUNTIME_CLASS(AActor));
 	}
 	return states;
 }
 
-static TypeInfo *sgClass;
+static PClass *sgClass;
 static BYTE *sgDefaults;
 
 static void ApplyActorDefault (int defnum, const char *datastr, int dataint)
 {
 	int datasound = 0;
 	FState *datastate = NULL;
-	const TypeInfo *datatype;
+	const PClass *datatype;
 
 	if (defnum <= ADEF_LastString)
 	{
@@ -134,10 +134,10 @@ static void ApplyActorDefault (int defnum, const char *datastr, int dataint)
 	case ADEF_Weapon_SisterType:
 	case ADEF_Weapon_ProjectileType:
 	case ADEF_PowerupGiver_Powerup:
-		datatype = TypeInfo::FindType (datastr);
+		datatype = PClass::FindClass (datastr);
 		if (datatype == NULL)
 		{
-			I_FatalError ("Unknown class %s in %s's default list", datastr, sgClass->Name+1);
+			I_FatalError ("Unknown class %s in %s's default list", datastr, sgClass->TypeName.GetChars());
 		}
 		break;
 
diff --git a/src/infomacros.h b/src/infomacros.h
index 655dc9601..ecda271bf 100644
--- a/src/infomacros.h
+++ b/src/infomacros.h
@@ -173,12 +173,12 @@ public:
 
 #define BEGIN_DEFAULTS(actor,game,ednum,spawnid) \
 	BEGIN_DEFAULTS_PRE(actor) \
-	RUNTIME_CLASS(actor), &actor::States[0], NULL, countof(actor::States), \
+	RUNTIME_CLASS(actor), &actor::States[0], countof(actor::States), \
 	BEGIN_DEFAULTS_POST(actor,game,ednum,spawnid)
 
 #define BEGIN_STATELESS_DEFAULTS(actor,game,ednum,spawnid) \
 	BEGIN_DEFAULTS_PRE(actor) \
-	RUNTIME_CLASS(actor), NULL, NULL, 0, \
+	RUNTIME_CLASS(actor), NULL, 0, \
 	BEGIN_DEFAULTS_POST(actor,game,ednum,spawnid)
 
 // IMPLEMENT_ACTOR combines IMPLEMENT_CLASS and BEGIN_DEFAULTS
diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp
index 2468221cc..04fabeeb5 100644
--- a/src/m_cheat.cpp
+++ b/src/m_cheat.cpp
@@ -48,7 +48,7 @@
 
 void cht_DoCheat (player_t *player, int cheat)
 {
-	static const TypeInfo *BeholdPowers[9] =
+	static const PClass *BeholdPowers[9] =
 	{
 		RUNTIME_CLASS(APowerInvulnerable),
 		RUNTIME_CLASS(APowerStrength),
@@ -60,7 +60,7 @@ void cht_DoCheat (player_t *player, int cheat)
 		RUNTIME_CLASS(APowerMask),
 		RUNTIME_CLASS(APowerTargeter)
 	};
-	const TypeInfo *type;
+	const PClass *type;
 	AInventory *item;
 	const char *msg = "";
 	char msgbuild[32];
@@ -130,7 +130,7 @@ void cht_DoCheat (player_t *player, int cheat)
 			}
 		}
 		else if (P_MorphPlayer (player,
-			TypeInfo::FindType (gameinfo.gametype==GAME_Heretic?"ChickenPlayer":"PigPlayer")))
+			PClass::FindClass (gameinfo.gametype == GAME_Heretic ? NAME_ChickenPlayer : NAME_PigPlayer)))
 		{
 			msg = "You feel strange...";
 		}
@@ -164,7 +164,7 @@ void cht_DoCheat (player_t *player, int cheat)
 	case CHT_CHAINSAW:
 		if (player->mo != NULL)
 		{
-			type = TypeInfo::FindType ("Chainsaw");
+			type = PClass::FindClass ("Chainsaw");
 			if (player->mo->FindInventory (type) == NULL)
 			{
 				player->mo->GiveInventoryType (type);
@@ -409,7 +409,7 @@ void cht_DoCheat (player_t *player, int cheat)
 		Printf ("%s is a cheater: %s\n", player->userinfo.netname, msg);
 }
 
-void GiveSpawner (player_t *player, const TypeInfo *type, int amount)
+void GiveSpawner (player_t *player, const PClass *type, int amount)
 {
 	AInventory *item = static_cast<AInventory *>
 		(Spawn (type, player->mo->x, player->mo->y, player->mo->z));
@@ -448,7 +448,7 @@ void cht_Give (player_t *player, char *name, int amount)
 {
 	BOOL giveall;
 	int i;
-	const TypeInfo *type;
+	const PClass *type;
 
 	if (player != &players[consoleplayer])
 		Printf ("%s is a cheater: give %s\n", player->userinfo.netname, name);
@@ -491,15 +491,15 @@ void cht_Give (player_t *player, char *name, int amount)
 		// Select the correct type of backpack based on the game
 		if (gameinfo.gametype == GAME_Heretic)
 		{
-			type = TypeInfo::FindType ("BagOfHolding");
+			type = PClass::FindClass ("BagOfHolding");
 		}
 		else if (gameinfo.gametype == GAME_Strife)
 		{
-			type = TypeInfo::FindType ("AmmoSatchel");
+			type = PClass::FindClass ("AmmoSatchel");
 		}
 		else if (gameinfo.gametype == GAME_Doom)
 		{
-			type = TypeInfo::FindType ("Backpack");
+			type = PClass::FindClass ("Backpack");
 		}
 		else
 		{ // Hexen doesn't have a backpack, foo!
@@ -518,11 +518,11 @@ void cht_Give (player_t *player, char *name, int amount)
 	{
 		// Find every unique type of ammo. Give it to the player if
 		// he doesn't have it already, and set each to its maximum.
-		for (unsigned int i = 0; i < TypeInfo::m_Types.Size(); ++i)
+		for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
 		{
-			const TypeInfo *type = TypeInfo::m_Types[i];
+			const PClass *type = PClass::m_Types[i];
 
-			if (type->ParentType == RUNTIME_CLASS(AAmmo))
+			if (type->ParentClass == RUNTIME_CLASS(AAmmo))
 			{
 				AInventory *ammo = player->mo->FindInventory (type);
 				if (ammo == NULL)
@@ -574,14 +574,14 @@ void cht_Give (player_t *player, char *name, int amount)
 
 	if (giveall || stricmp (name, "keys") == 0)
 	{
-		for (unsigned int i = 0; i < TypeInfo::m_Types.Size(); ++i)
+		for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
 		{
-			if (TypeInfo::m_Types[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
+			if (PClass::m_Types[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
 			{
-				AKey *key = (AKey *)GetDefaultByType (TypeInfo::m_Types[i]);
+				AKey *key = (AKey *)GetDefaultByType (PClass::m_Types[i]);
 				if (key->KeyNumber != 0)
 				{
-					key = static_cast<AKey *>(Spawn (TypeInfo::m_Types[i], 0,0,0));
+					key = static_cast<AKey *>(Spawn (PClass::m_Types[i], 0,0,0));
 					if (!key->TryPickup (player->mo))
 					{
 						key->Destroy ();
@@ -596,9 +596,9 @@ void cht_Give (player_t *player, char *name, int amount)
 	if (giveall || stricmp (name, "weapons") == 0)
 	{
 		AWeapon *savedpending = player->PendingWeapon;
-		for (unsigned int i = 0; i < TypeInfo::m_Types.Size(); ++i)
+		for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
 		{
-			type = TypeInfo::m_Types[i];
+			type = PClass::m_Types[i];
 			if (type != RUNTIME_CLASS(AWeapon) &&
 				type->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
 			{
@@ -617,9 +617,9 @@ void cht_Give (player_t *player, char *name, int amount)
 
 	if (giveall || stricmp (name, "artifacts") == 0)
 	{
-		for (unsigned int i = 0; i < TypeInfo::m_Types.Size(); ++i)
+		for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
 		{
-			type = TypeInfo::m_Types[i];
+			type = PClass::m_Types[i];
 			if (type->IsDescendantOf (RUNTIME_CLASS(AInventory)))
 			{
 				AInventory *def = (AInventory*)GetDefaultByType (type);
@@ -638,9 +638,9 @@ void cht_Give (player_t *player, char *name, int amount)
 
 	if (giveall || stricmp (name, "puzzlepieces") == 0)
 	{
-		for (unsigned int i = 0; i < TypeInfo::m_Types.Size(); ++i)
+		for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
 		{
-			type = TypeInfo::m_Types[i];
+			type = PClass::m_Types[i];
 			if (type->IsDescendantOf (RUNTIME_CLASS(APuzzleItem)))
 			{
 				AInventory *def = (AInventory*)GetDefaultByType (type);
@@ -657,7 +657,7 @@ void cht_Give (player_t *player, char *name, int amount)
 	if (giveall)
 		return;
 
-	type = TypeInfo::IFindType (name);
+	type = PClass::FindClass (name);
 	if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AInventory)))
 	{
 		if (player == &players[consoleplayer])
diff --git a/src/m_menu.cpp b/src/m_menu.cpp
index bec485bf1..044cfcda4 100644
--- a/src/m_menu.cpp
+++ b/src/m_menu.cpp
@@ -217,7 +217,7 @@ static DCanvas	*FireScreen;
 static byte		FireRemap[256];
 
 static char		*genders[3] = { "male", "female", "other" };
-static const TypeInfo *PlayerClass;
+static const PClass *PlayerClass;
 static FState	*PlayerState;
 static int		PlayerTics;
 static int		PlayerRotation;
@@ -1803,7 +1803,7 @@ static void M_PlayerSetupTicker (void)
 	// Based on code in f_finale.c
 	if (gameinfo.gametype == GAME_Hexen)
 	{
-		const TypeInfo *oldclass = PlayerClass;
+		const PClass *oldclass = PlayerClass;
 
 		PickPlayerClass ();
 		if (PlayerClass != oldclass)
@@ -3192,15 +3192,15 @@ static void PickPlayerClass ()
 {
 	if (gameinfo.gametype & (GAME_Doom|GAME_Strife))
 	{
-		PlayerClass = TypeInfo::FindType ("DoomPlayer");
+		PlayerClass = PClass::FindClass (NAME_DoomPlayer);
 	}
 	else if (gameinfo.gametype == GAME_Heretic)
 	{
-		PlayerClass = TypeInfo::FindType ("HereticPlayer");
+		PlayerClass = PClass::FindClass (NAME_HereticPlayer);
 	}
 	else
 	{
-		static const char *classnames[3] = { "FighterPlayer", "ClericPlayer", "MagePlayer" };
+		static const ENamedName classnames[3] = { NAME_FighterPlayer, NAME_ClericPlayer, NAME_MagePlayer };
 
 		int nowtype = players[consoleplayer].userinfo.PlayerClass;
 
@@ -3209,6 +3209,6 @@ static void PickPlayerClass ()
 			nowtype = (MenuTime>>7) % 3;
 		}
 
-		PlayerClass = TypeInfo::FindType (classnames[nowtype]);
+		PlayerClass = PClass::FindClass (classnames[nowtype]);
 	}
 }
diff --git a/src/name.cpp b/src/name.cpp
index 0ef2737a2..44d691eda 100644
--- a/src/name.cpp
+++ b/src/name.cpp
@@ -99,8 +99,8 @@ int FName::NameManager::FindName (const char *text, bool noCreate)
 		return 0;
 	}
 
-	DWORD hash = MakeKey (text);
-	DWORD bucket = hash % HASH_SIZE;
+	unsigned int hash = MakeKey (text);
+	unsigned int bucket = hash % HASH_SIZE;
 	int scanner = Buckets[bucket];
 
 	// See if the name already exists.
@@ -150,7 +150,7 @@ void FName::NameManager::InitBuckets ()
 //
 //==========================================================================
 
-int FName::NameManager::AddName (const char *text, DWORD hash, DWORD bucket)
+int FName::NameManager::AddName (const char *text, unsigned int hash, unsigned int bucket)
 {
 	char *textstore;
 	NameBlock *block = Blocks;
diff --git a/src/name.h b/src/name.h
index d892ca18f..0763cf781 100644
--- a/src/name.h
+++ b/src/name.h
@@ -88,7 +88,7 @@ private:
 	struct NameEntry
 	{
 		char *Text;
-		DWORD Hash;
+		unsigned int Hash;
 		int NextHash;
 	};
 
@@ -108,7 +108,7 @@ private:
 		int Buckets[HASH_SIZE];
 
 		int FindName (const char *text, bool noCreate);
-		int AddName (const char *text, DWORD hash, DWORD bucket);
+		int AddName (const char *text, unsigned int hash, unsigned int bucket);
 		NameBlock *AddBlock (size_t len);
 		void InitBuckets ();
 		bool Inited;
diff --git a/src/namedef.h b/src/namedef.h
index e93b22847..f6f51e952 100644
--- a/src/namedef.h
+++ b/src/namedef.h
@@ -1,6 +1,9 @@
 // 'None' must always be the first name.
 xx(None)
 
+xx(Super)
+xx(Object)
+
 // Hexen sound sequence names
 xx(Platform)
 xx(PlatformMetal)
@@ -17,10 +20,6 @@ xx(DoorCreak)
 xx(DoorMetal2)
 xx(Wind)
 
-#if 0
-xx(Super)
-xx(Object)
-
 // Special bosses A_BossDeath knows about
 xx(Fatso)
 xx(Arachnotron)
@@ -31,6 +30,11 @@ xx(Ironlich)
 xx(Minotaur)
 xx(Sorcerer2)
 
+// P_SpawnMapThing checks for these as health items (I smell a FIXME)
+xx(Berserk)
+xx(Soulsphere)
+xx(Megasphere)		// also counts as armor for P_SpawnMapThing
+
 // Standard player classes
 xx(DoomPlayer)
 xx(HereticPlayer)
@@ -38,6 +42,31 @@ xx(StrifePlayer)
 xx(FighterPlayer)
 xx(ClericPlayer)
 xx(MagePlayer)
+xx(ChickenPlayer)
+xx(PigPlayer)
+
+// Flechette names for the different Hexen player classes
+xx(ArtiPoisonBag1)
+xx(ArtiPoisonBag2)
+xx(ArtiPoisonBag3)
+
+// Strife quests
+xx(QuestItem)
+
+// Auto-usable health items
+xx(ArtiHealth)
+xx(ArtiSuperHealth)
+xx(MedicalKit)
+xx(MedPatch)
+
+// The Wings of Wrath
+xx(ArtiFly)
+
+// Doom ammo types
+xx(Clip)
+xx(Shell)
+xx(RocketAmmo)
+xx(Cell)
 
 // Weapon names for the Strife status bar
 xx(StrifeCrossbow)
@@ -47,15 +76,10 @@ xx(MiniMissileLauncher)
 xx(StrifeGrenadeLauncher)
 xx(Mauler)
 
-// Flechette names for the different Hexen player classes
-xx(ArtiPoisonBag1)
-xx(ArtiPoisonBag2)
-xx(ArtiPoisonBag3)
+xx(Chicken)
+xx(Pig)
 
-// P_SpawnMapThing checks for these as health items (I smell a FIXME)
-xx(Berserk)
-xx(Soulsphere)
-xx(Megasphere)		// also counts as armor for P_SpawnMapThing
+#if 0
 
 // Standard animator names.
 xx(Spawn)
diff --git a/src/p_acs.cpp b/src/p_acs.cpp
index d862bf49d..93863d3b1 100644
--- a/src/p_acs.cpp
+++ b/src/p_acs.cpp
@@ -167,7 +167,7 @@ static void ClearInventory (AActor *activator)
 //
 //============================================================================
 
-static void DoGiveInv (AActor *actor, const TypeInfo *info, int amount)
+static void DoGiveInv (AActor *actor, const PClass *info, int amount)
 {
 	AWeapon *savedPendingWeap = actor->player != NULL
 		? actor->player->PendingWeapon : NULL;
@@ -222,17 +222,17 @@ static void DoGiveInv (AActor *actor, const TypeInfo *info, int amount)
 
 static void GiveInventory (AActor *activator, const char *type, int amount)
 {
-	const TypeInfo *info;
+	const PClass *info;
 
 	if (amount <= 0 || type == NULL)
 	{
 		return;
 	}
-	if (strcmp (type, "Armor") == 0)
+	if (stricmp (type, "Armor") == 0)
 	{
 		type = "BasicArmorPickup";
 	}
-	info = TypeInfo::FindType (type);
+	info = PClass::FindClass (type);
 	if (info == NULL)
 	{
 		Printf ("ACS: I don't know what %s is.\n", type);
@@ -263,7 +263,7 @@ static void GiveInventory (AActor *activator, const char *type, int amount)
 //
 //============================================================================
 
-static void DoTakeInv (AActor *actor, const TypeInfo *info, int amount)
+static void DoTakeInv (AActor *actor, const PClass *info, int amount)
 {
 	AInventory *item = actor->FindInventory (info);
 	if (item != NULL)
@@ -274,7 +274,7 @@ static void DoTakeInv (AActor *actor, const TypeInfo *info, int amount)
 			// If it's not ammo, destroy it. Ammo needs to stick around, even
 			// when it's zero for the benefit of the weapons that use it and 
 			// to maintain the maximum ammo amounts a backpack might have given.
-			if (item->GetClass()->ParentType != RUNTIME_CLASS(AAmmo))
+			if (item->GetClass()->ParentClass != RUNTIME_CLASS(AAmmo))
 			{
 				item->Destroy ();
 			}
@@ -296,7 +296,7 @@ static void DoTakeInv (AActor *actor, const TypeInfo *info, int amount)
 
 static void TakeInventory (AActor *activator, const char *type, int amount)
 {
-	const TypeInfo *info;
+	const PClass *info;
 
 	if (type == NULL)
 	{
@@ -310,7 +310,7 @@ static void TakeInventory (AActor *activator, const char *type, int amount)
 	{
 		return;
 	}
-	info = TypeInfo::FindType (type);
+	info = PClass::FindClass (type);
 	if (info == NULL)
 	{
 		return;
@@ -342,16 +342,16 @@ static int CheckInventory (AActor *activator, const char *type)
 	if (activator == NULL || type == NULL)
 		return 0;
 
-	if (strcmp (type, "Armor") == 0)
+	if (stricmp (type, "Armor") == 0)
 	{
 		type = "BasicArmor";
 	}
-	else if (strcmp (type, "Health") == 0)
+	else if (stricmp (type, "Health") == 0)
 	{
 		return activator->health;
 	}
 
-	const TypeInfo *info = TypeInfo::FindType (type);
+	const PClass *info = PClass::FindClass (type);
 	AInventory *item = activator->FindInventory (info);
 	return item ? item->Amount : 0;
 }
@@ -1599,7 +1599,7 @@ int DLevelScript::Random (int min, int max)
 int DLevelScript::ThingCount (int type, int tid)
 {
 	AActor *actor;
-	const TypeInfo *kind;
+	const PClass *kind;
 	int count = 0;
 
 	if (type >= MAX_SPAWNABLES)
@@ -1732,7 +1732,7 @@ void DLevelScript::SetLineTexture (int lineid, int side, int position, int name)
 
 int DLevelScript::DoSpawn (int type, fixed_t x, fixed_t y, fixed_t z, int tid, int angle)
 {
-	const TypeInfo *info = TypeInfo::FindType (FBehavior::StaticLookupString (type));
+	const PClass *info = PClass::FindClass (FBehavior::StaticLookupString (type));
 	AActor *actor = NULL;
 
 	if (info != NULL)
@@ -3225,7 +3225,7 @@ int DLevelScript::RunScript ()
 				}
 				else if (activator)
 				{
-					workwhere += sprintf (workwhere, "%s", RUNTIME_TYPE(activator)->Name+1);
+					workwhere += sprintf (workwhere, "%s", RUNTIME_TYPE(activator)->TypeName.GetChars());
 				}
 				else
 				{
@@ -3740,10 +3740,10 @@ int DLevelScript::RunScript ()
 		case PCD_GETAMMOCAPACITY:
 			if (activator != NULL)
 			{
-				const TypeInfo *type = TypeInfo::FindType (FBehavior::StaticLookupString (STACK(1)));
+				const PClass *type = PClass::FindClass (FBehavior::StaticLookupString (STACK(1)));
 				AInventory *item;
 
-				if (type != NULL && type->ParentType == RUNTIME_CLASS(AAmmo))
+				if (type != NULL && type->ParentClass == RUNTIME_CLASS(AAmmo))
 				{
 					item = activator->FindInventory (type);
 					if (item != NULL)
@@ -3769,10 +3769,10 @@ int DLevelScript::RunScript ()
 		case PCD_SETAMMOCAPACITY:
 			if (activator != NULL)
 			{
-				const TypeInfo *type = TypeInfo::FindType (FBehavior::StaticLookupString (STACK(2)));
+				const PClass *type = PClass::FindClass (FBehavior::StaticLookupString (STACK(2)));
 				AInventory *item;
 
-				if (type != NULL && type->ParentType == RUNTIME_CLASS(AAmmo))
+				if (type != NULL && type->ParentClass == RUNTIME_CLASS(AAmmo))
 				{
 					item = activator->FindInventory (type);
 					if (item != NULL)
@@ -4075,7 +4075,7 @@ int DLevelScript::RunScript ()
 			else
 			{
 				STACK(1) = 0 == strcmp (FBehavior::StaticLookupString (STACK(1)),
-					activator->player->ReadyWeapon->GetClass()->Name+1);
+					activator->player->ReadyWeapon->GetClass()->TypeName.GetChars());
 			}
 			break;
 
@@ -4086,7 +4086,7 @@ int DLevelScript::RunScript ()
 			}
 			else
 			{
-				AInventory *item = activator->FindInventory (TypeInfo::FindType (
+				AInventory *item = activator->FindInventory (PClass::FindClass (
 					FBehavior::StaticLookupString (STACK(1))));
 
 				if (item == NULL || !item->IsKindOf (RUNTIME_CLASS(AWeapon)))
@@ -4142,7 +4142,7 @@ int DLevelScript::RunScript ()
 
 		case PCD_SETMARINESPRITE:
 			{
-				const TypeInfo *type = TypeInfo::FindType (FBehavior::StaticLookupString (STACK(1)));
+				const PClass *type = PClass::FindClass (FBehavior::StaticLookupString (STACK(1)));
 
 				if (type != NULL)
 				{
diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp
index 7b65b9a47..52488347f 100644
--- a/src/p_conversation.cpp
+++ b/src/p_conversation.cpp
@@ -56,7 +56,7 @@ struct TeaserSpeech
 
 static FRandom pr_randomspeech("RandomSpeech");
 
-void GiveSpawner (player_t *player, const TypeInfo *type);
+void GiveSpawner (player_t *player, const PClass *type);
 
 TArray<FStrifeDialogueNode *> StrifeDialogues;
 
@@ -64,7 +64,7 @@ TArray<FStrifeDialogueNode *> StrifeDialogues;
 // to their index in the mobjinfo table. This table indexes all
 // the Strife actor types in the order Strife had them and is
 // initialized as part of the actor's setup in infodefaults.cpp.
-const TypeInfo *StrifeTypes[344];
+const PClass *StrifeTypes[344];
 
 static menu_t ConversationMenu;
 static TArray<menuitem_t> ConversationItems;
@@ -172,11 +172,11 @@ static const char *const RandomLines[NUM_RANDOM_TALKERS][NUM_RANDOM_LINES+1] =
 //
 // GetStrifeType
 //
-// Given an item type number, returns the corresponding TypeInfo.
+// Given an item type number, returns the corresponding PClass.
 //
 //============================================================================
 
-static const TypeInfo *GetStrifeType (int typenum)
+static const PClass *GetStrifeType (int typenum)
 {
 	if (typenum > 0 && typenum < 344)
 	{
@@ -322,7 +322,7 @@ static FStrifeDialogueNode *ReadRetailNode (FWadLump *lump, DWORD &prevSpeakerTy
 	FStrifeDialogueNode *node;
 	Speech speech;
 	char fullsound[16];
-	const TypeInfo *type;
+	const PClass *type;
 	int j;
 
 	node = new FStrifeDialogueNode;
@@ -392,7 +392,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FWadLump *lump, DWORD &prevSpeakerTy
 	FStrifeDialogueNode *node;
 	TeaserSpeech speech;
 	char fullsound[16];
-	const TypeInfo *type;
+	const PClass *type;
 	int j;
 
 	node = new FStrifeDialogueNode;
@@ -614,7 +614,7 @@ static int FindNode (const FStrifeDialogueNode *node)
 //
 //============================================================================
 
-static bool CheckStrifeItem (const TypeInfo *itemtype, int amount=-1)
+static bool CheckStrifeItem (const PClass *itemtype, int amount=-1)
 {
 	AInventory *item;
 
@@ -637,13 +637,13 @@ static bool CheckStrifeItem (const TypeInfo *itemtype, int amount=-1)
 //
 //============================================================================
 
-static void TakeStrifeItem (const TypeInfo *itemtype, int amount)
+static void TakeStrifeItem (const PClass *itemtype, int amount)
 {
 	if (itemtype == NULL || amount == 0)
 		return;
 
 	// Don't take quest items.
-	if (itemtype->IsDescendantOf (TypeInfo::FindType("QuestItem")))
+	if (itemtype->IsDescendantOf (PClass::FindClass(NAME_QuestItem)))
 		return;
 
 	// Don't take keys
@@ -1001,7 +1001,7 @@ static void PickConversationReply ()
 		{
 			// Trying to give a non-inventory item.
 			takestuff = false;
-			Printf("Attempting to give non-inventory item %s\n", reply->GiveType->Name+1);
+			Printf("Attempting to give non-inventory item %s\n", reply->GiveType->TypeName.GetChars());
 		}
 	}
 
diff --git a/src/p_conversation.h b/src/p_conversation.h
index 3945ad39c..435226348 100644
--- a/src/p_conversation.h
+++ b/src/p_conversation.h
@@ -16,11 +16,11 @@ struct brokenlines_t;
 struct FStrifeDialogueNode
 {
 	~FStrifeDialogueNode ();
-	const TypeInfo *DropType;
-	const TypeInfo *ItemCheck[3];
+	const PClass *DropType;
+	const PClass *ItemCheck[3];
 	int ItemCheckNode;	// index into StrifeDialogues
 
-	const TypeInfo *SpeakerType;
+	const PClass *SpeakerType;
 	char *SpeakerName;
 	int SpeakerVoice;
 	int Backdrop;
@@ -35,8 +35,8 @@ struct FStrifeDialogueReply
 	~FStrifeDialogueReply ();
 
 	FStrifeDialogueReply *Next;
-	const TypeInfo *GiveType;
-	const TypeInfo *ItemCheck[3];
+	const PClass *GiveType;
+	const PClass *ItemCheck[3];
 	int ItemCheckAmount[3];
 	char *Reply;
 	char *QuickYes;
@@ -54,7 +54,7 @@ extern TArray<FStrifeDialogueNode *> StrifeDialogues;
 // to their index in the mobjinfo table. This table indexes all
 // the Strife actor types in the order Strife had them and is
 // initialized as part of the actor's setup in infodefaults.cpp.
-extern const TypeInfo *StrifeTypes[344];
+extern const PClass *StrifeTypes[344];
 
 void P_LoadStrifeConversations (const char *mapname);
 void P_FreeStrifeConversations ();
diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp
index 8f824204d..7149ab466 100644
--- a/src/p_enemy.cpp
+++ b/src/p_enemy.cpp
@@ -2161,7 +2161,7 @@ void A_XXScream (AActor *actor)
 //---------------------------------------------------------------------------
 CVAR(Int, sv_dropstyle, 0, CVAR_SERVERINFO | CVAR_ARCHIVE);
 
-AInventory *P_DropItem (AActor *source, const TypeInfo *type, int special, int chance)
+AInventory *P_DropItem (AActor *source, const PClass *type, int special, int chance)
 {
 	if (type != NULL && pr_dropitem() <= chance)
 	{
@@ -2367,7 +2367,7 @@ void A_BossDeath (AActor *actor)
 	FSpecialAction *sa = level.info->specialactions;
 	while (sa)
 	{
-		if (FName(actor->GetClass()->Name+1) == sa->Type)
+		if (FName(actor->GetClass()->TypeName.GetChars()) == sa->Type)
 		{
 			if (!checked && !CheckBossDeath(actor))
 			{
@@ -2393,24 +2393,19 @@ void A_BossDeath (AActor *actor)
 						LEVEL_SORCERER2SPECIAL)) == 0)
 		return;
 
-	if (strcmp (RUNTIME_TYPE(actor)->Name+1, "Fatso") == 0)
-		type = MT_FATSO;
-	else if (strcmp (RUNTIME_TYPE(actor)->Name+1, "Arachnotron") == 0)
-		type = MT_BABY;
-	else if (strcmp (RUNTIME_TYPE(actor)->Name+1, "BaronOfHell") == 0)
-		type = MT_BRUISER;
-	else if (strcmp (RUNTIME_TYPE(actor)->Name+1, "Cyberdemon") == 0)
-		type = MT_CYBORG;
-	else if (strcmp (RUNTIME_TYPE(actor)->Name+1, "SpiderMastermind") == 0)
-		type = MT_SPIDER;
-	else if (strcmp (RUNTIME_TYPE(actor)->Name+1, "Ironlich") == 0)
-		type = MT_HEAD;
-	else if (strcmp (RUNTIME_TYPE(actor)->Name+1, "Minotaur") == 0)
-		type = MT_MINOTAUR;
-	else if (strcmp (RUNTIME_TYPE(actor)->Name+1, "Sorcerer2") == 0)
-		type = MT_SORCERER2;
-	else
-		return;
+	const PClass *actorType = actor->GetClass();
+	switch (actorType->TypeName)
+	{
+	case NAME_Fatso:			type = MT_FATSO;		break;
+	case NAME_Arachnotron:		type = MT_BABY;			break;
+	case NAME_BaronOfHell:		type = MT_BRUISER;		break;
+	case NAME_Cyberdemon:		type = MT_CYBORG;		break;
+	case NAME_SpiderMastermind:	type = MT_SPIDER;		break;
+	case NAME_Ironlich:			type = MT_HEAD;			break;
+	case NAME_Minotaur:			type = MT_MINOTAUR;		break;
+	case NAME_Sorcerer2:		type = MT_SORCERER2;	break;
+	default:					return;
+	}
 
 	if (
 		((level.flags & LEVEL_MAP07SPECIAL) && (type == MT_FATSO || type == MT_BABY)) ||
diff --git a/src/p_enemy.h b/src/p_enemy.h
index 8bb733bf0..064455327 100644
--- a/src/p_enemy.h
+++ b/src/p_enemy.h
@@ -26,10 +26,10 @@ BOOL P_Move (AActor *actor);
 BOOL P_TryWalk (AActor *actor);
 void P_NewChaseDir (AActor *actor);
 BOOL P_LookForPlayers (AActor *actor, BOOL allaround);
-AInventory *P_DropItem (AActor *source, const TypeInfo *type, int special, int chance);
+AInventory *P_DropItem (AActor *source, const PClass *type, int special, int chance);
 inline AInventory *P_DropItem (AActor *source, const char *type, int special, int chance)
 {
-	return P_DropItem (source, TypeInfo::FindType (type), special, chance);
+	return P_DropItem (source, PClass::FindClass (type), special, chance);
 }
 void P_TossItem (AActor *item);
 
diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp
index be47583df..e4b597fb1 100644
--- a/src/p_interaction.cpp
+++ b/src/p_interaction.cpp
@@ -702,8 +702,8 @@ void P_AutoUseHealth(player_t *player, int saveHealth)
 {
 	int i;
 	int count;
-	const TypeInfo *normalType = TypeInfo::FindType ("ArtiHealth");
-	const TypeInfo *superType = TypeInfo::FindType ("ArtiSuperHealth");
+	const PClass *normalType = PClass::FindClass (NAME_ArtiHealth);
+	const PClass *superType = PClass::FindClass (NAME_ArtiSuperHealth);
 	AInventory *normalItem = player->mo->FindInventory (normalType);
 	AInventory *superItem = player->mo->FindInventory (superType);
 	int normalAmount, superAmount;
@@ -773,11 +773,11 @@ void P_AutoUseHealth(player_t *player, int saveHealth)
 
 void P_AutoUseStrifeHealth (player_t *player)
 {
-	static const char *healthnames[2] = { "MedicalKit", "MedPatch" };
+	static const ENamedName healthnames[2] = { NAME_MedicalKit, NAME_MedPatch };
 
 	for (int i = 0; i < 2; ++i)
 	{
-		const TypeInfo *type = TypeInfo::FindType (healthnames[i]);
+		const PClass *type = PClass::FindClass (healthnames[i]);
 
 		while (player->health < 50)
 		{
diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp
index ccea1a58e..66ed4f536 100644
--- a/src/p_lnspec.cpp
+++ b/src/p_lnspec.cpp
@@ -2117,7 +2117,7 @@ FUNC(LS_SetPlayerProperty)
 	// Add or remove a power
 	if (arg2 >= PROP_INVULNERABILITY && arg2 <= PROP_SPEED)
 	{
-		static const TypeInfo *powers[11] =
+		static const PClass *powers[11] =
 		{
 			RUNTIME_CLASS(APowerInvulnerable),
 			RUNTIME_CLASS(APowerStrength),
diff --git a/src/p_local.h b/src/p_local.h
index fa45ed2fc..0308b0099 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -96,7 +96,7 @@ void P_ThrustMobj (AActor *mo, angle_t angle, fixed_t move);
 int P_FaceMobj (AActor *source, AActor *target, angle_t *delta);
 bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax);
 
-AActor *P_SpawnPuff (const TypeInfo *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, bool hit=false);
+AActor *P_SpawnPuff (const PClass *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, bool hit=false);
 void	P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AActor *originator);
 void	P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator);
 void	P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator);
@@ -104,18 +104,18 @@ void	P_RipperBlood (AActor *mo, AActor *bleeder);
 int		P_GetThingFloorType (AActor *thing);
 void	P_ExplodeMissile (AActor *missile, line_t *explodeline);
 
-AActor *P_SpawnMissile (AActor* source, AActor* dest, const TypeInfo *type);
-AActor *P_SpawnMissileZ (AActor* source, fixed_t z, AActor* dest, const TypeInfo *type);
-AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, AActor *source, AActor *dest, const TypeInfo *type);
-AActor *P_SpawnMissileAngle (AActor *source, const TypeInfo *type, angle_t angle, fixed_t momz);
-AActor *P_SpawnMissileAngleSpeed (AActor *source, const TypeInfo *type, angle_t angle, fixed_t momz, fixed_t speed);
-AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z, const TypeInfo *type, angle_t angle, fixed_t momz);
-AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z, const TypeInfo *type, angle_t angle, fixed_t momz, fixed_t speed, AActor *owner=NULL);
-AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const TypeInfo *type);
+AActor *P_SpawnMissile (AActor* source, AActor* dest, const PClass *type);
+AActor *P_SpawnMissileZ (AActor* source, fixed_t z, AActor* dest, const PClass *type);
+AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, AActor *source, AActor *dest, const PClass *type);
+AActor *P_SpawnMissileAngle (AActor *source, const PClass *type, angle_t angle, fixed_t momz);
+AActor *P_SpawnMissileAngleSpeed (AActor *source, const PClass *type, angle_t angle, fixed_t momz, fixed_t speed);
+AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z, const PClass *type, angle_t angle, fixed_t momz);
+AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z, const PClass *type, angle_t angle, fixed_t momz, fixed_t speed, AActor *owner=NULL);
+AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PClass *type);
 
-AActor *P_SpawnPlayerMissile (AActor* source, const TypeInfo *type);
-AActor *P_SpawnPlayerMissile (AActor *source, const TypeInfo *type, angle_t angle);
-AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, const TypeInfo *type, angle_t angle);
+AActor *P_SpawnPlayerMissile (AActor* source, const PClass *type);
+AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle);
+AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, const PClass *type, angle_t angle);
 
 void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz);
 
@@ -123,7 +123,7 @@ void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz);
 // [RH] P_THINGS
 //
 #define MAX_SPAWNABLES	(256)
-extern const TypeInfo *SpawnableThings[MAX_SPAWNABLES];
+extern const PClass *SpawnableThings[MAX_SPAWNABLES];
 
 bool	P_Thing_Spawn (int tid, int type, angle_t angle, bool fog, int newtid);
 bool	P_Thing_Projectile (int tid, int type, angle_t angle,
@@ -298,7 +298,7 @@ extern	AActor*	linetarget; 	// who got hit (or NULL)
 extern	AActor *PuffSpawned;	// points to last puff spawned
 
 fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, fixed_t vrange=0);
-void	P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, int damageType, const TypeInfo *pufftype);
+void	P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, int damageType, const PClass *pufftype);
 void	P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch);
 void	P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch);
 void	P_TraceBleed (int damage, AActor *target, AActor *missile);		// missile version
@@ -347,7 +347,7 @@ void P_TouchSpecialThing (AActor *special, AActor *toucher);
 void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, int mod, int flags=0);
 
 bool P_GiveBody (AActor *actor, int num);
-bool P_MorphPlayer (player_t *player, const TypeInfo *morphClass);
+bool P_MorphPlayer (player_t *player, const PClass *morphClass);
 void P_PoisonPlayer (player_t *player, AActor *poisoner, AActor *source, int poison);
 void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPainSound);
 
diff --git a/src/p_map.cpp b/src/p_map.cpp
index 733b26fc0..8c6d1c71f 100644
--- a/src/p_map.cpp
+++ b/src/p_map.cpp
@@ -2674,7 +2674,7 @@ static bool CheckForSpectral (FTraceResults &res)
 }
 
 void P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
-				   int pitch, int damage, int damageType, const TypeInfo *pufftype)
+				   int pitch, int damage, int damageType, const PClass *pufftype)
 {
 	fixed_t vx, vy, vz, shootz;
 	FTraceResults trace;
@@ -4313,7 +4313,7 @@ msecnode_t *P_AddSecnode (sector_t *s, AActor *thing, msecnode_t *nextnode)
 
 	if (s == 0)
 	{
-		I_FatalError ("AddSecnode of 0 for %s\n", thing->_StaticType.Name);
+		I_FatalError ("AddSecnode of 0 for %s\n", thing->_StaticType.TypeName.GetChars());
 	}
 
 	node = nextnode;
diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp
index 7f35c3f8a..423a7e9e6 100644
--- a/src/p_maputl.cpp
+++ b/src/p_maputl.cpp
@@ -551,7 +551,7 @@ sector_t *AActor::LinkToWorldForMapThing ()
 						if (num >= 0 && num <= den)
 						{
 							DPrintf ("%s at (%ld,%ld) lies directly on line %d\n",
-								this->GetClass()->Name+1, x>>FRACBITS, y>>FRACBITS, ldef-lines);
+								this->GetClass()->TypeName.GetChars(), x>>FRACBITS, y>>FRACBITS, ldef-lines);
 							angle_t finean = R_PointToAngle2 (0, 0, ldef->dx, ldef->dy);
 							if (ldef->backsector != NULL && ldef->backsector == ssec->sector)
 							{
diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp
index ae880ed81..7f7efde0e 100644
--- a/src/p_mobj.cpp
+++ b/src/p_mobj.cpp
@@ -416,7 +416,6 @@ void MapThing::Serialize (FArchive &arc)
 
 AActor::AActor () throw()
 {
-	memset (&x, 0, (byte *)&this[1] - (byte *)&x);
 }
 
 AActor::AActor (const AActor &other) throw()
@@ -765,7 +764,7 @@ AInventory *AActor::DropInventory (AInventory *item)
 //
 //============================================================================
 
-AInventory *AActor::FindInventory (const TypeInfo *type) const
+AInventory *AActor::FindInventory (const PClass *type) const
 {
 	AInventory *item;
 
@@ -785,7 +784,7 @@ AInventory *AActor::FindInventory (const TypeInfo *type) const
 //
 //============================================================================
 
-AInventory *AActor::GiveInventoryType (const TypeInfo *type)
+AInventory *AActor::GiveInventoryType (const PClass *type)
 {
 	AInventory *item;
 
@@ -806,7 +805,7 @@ AInventory *AActor::GiveInventoryType (const TypeInfo *type)
 //
 //============================================================================
 
-bool AActor::GiveAmmo (const TypeInfo *type, int amount)
+bool AActor::GiveAmmo (const PClass *type, int amount)
 {
 	AInventory *item = static_cast<AInventory *>(Spawn (type, 0, 0, 0));
 	item->Amount = amount;
@@ -2992,7 +2991,7 @@ END_DEFAULTS
 //
 //==========================================================================
 
-AActor *AActor::StaticSpawn (const TypeInfo *type, fixed_t ix, fixed_t iy, fixed_t iz)
+AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t iz)
 {
 	if (type == NULL)
 	{
@@ -3001,12 +3000,12 @@ AActor *AActor::StaticSpawn (const TypeInfo *type, fixed_t ix, fixed_t iy, fixed
 
 	if (type->ActorInfo == NULL)
 	{
-		I_Error ("%s is not an actor\n", type->Name);
+		I_Error ("%s is not an actor\n", type->TypeName.GetChars());
 	}
 
 	AActor *actor;
 
-	actor = static_cast<AActor *>(const_cast<TypeInfo *>(type)->CreateNew ());
+	actor = static_cast<AActor *>(const_cast<PClass *>(type)->CreateNew ());
 
 	actor->x = actor->PrevX = ix;
 	actor->y = actor->PrevY = iy;
@@ -3323,19 +3322,19 @@ void P_SpawnPlayer (mapthing2_t *mthing)
 		p->CurrentPlayerClass = 0;
 		if (gameinfo.gametype == GAME_Doom)
 		{
-			p->cls = TypeInfo::FindType ("DoomPlayer");
+			p->cls = PClass::FindClass (NAME_DoomPlayer);
 		}
 		else if (gameinfo.gametype == GAME_Heretic)
 		{
-			p->cls = TypeInfo::FindType ("HereticPlayer");
+			p->cls = PClass::FindClass (NAME_HereticPlayer);
 		}
 		else if (gameinfo.gametype == GAME_Strife)
 		{
-			p->cls = TypeInfo::FindType ("StrifePlayer");
+			p->cls = PClass::FindClass (NAME_StrifePlayer);
 		}
 		else
 		{
-			static const char *classes[3] = { "FighterPlayer", "ClericPlayer", "MagePlayer" };
+			static const ENamedName classes[3] = { NAME_FighterPlayer, NAME_ClericPlayer, NAME_MagePlayer };
 			int type;
 
 			if (!deathmatch || !multiplayer)
@@ -3351,7 +3350,7 @@ void P_SpawnPlayer (mapthing2_t *mthing)
 				}
 			}
 			p->CurrentPlayerClass = type;
-			p->cls = TypeInfo::FindType (classes[type]);
+			p->cls = PClass::FindClass (classes[type]);
 		}
 	}
 
@@ -3429,14 +3428,14 @@ void P_SpawnPlayer (mapthing2_t *mthing)
 	// give all cards in death match mode
 	if (deathmatch)
 	{
-		for (i = 0; i < TypeInfo::m_Types.Size(); ++i)
+		for (i = 0; i < PClass::m_Types.Size(); ++i)
 		{
-			if (TypeInfo::m_Types[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
+			if (PClass::m_Types[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
 			{
-				AKey *key = (AKey *)GetDefaultByType (TypeInfo::m_Types[i]);
+				AKey *key = (AKey *)GetDefaultByType (PClass::m_Types[i]);
 				if (key->KeyNumber != 0)
 				{
-					key = static_cast<AKey *>(Spawn (TypeInfo::m_Types[i], 0,0,0));
+					key = static_cast<AKey *>(Spawn (PClass::m_Types[i], 0,0,0));
 					if (!key->TryPickup (p->mo))
 					{
 						key->Destroy ();
@@ -3490,7 +3489,7 @@ void P_SpawnPlayer (mapthing2_t *mthing)
 // [RH] position is used to weed out unwanted start spots
 void P_SpawnMapThing (mapthing2_t *mthing, int position)
 {
-	const TypeInfo *i;
+	const PClass *i;
 	int mask;
 	AActor *mobj;
 	fixed_t x, y, z;
@@ -3709,7 +3708,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
 			sprites[defaults->SpawnState->sprite.index].numframes == 0)
 		{
 			Printf ("%s at (%i, %i) has no frames\n",
-					i->Name+1, mthing->x, mthing->y);
+					i->TypeName.GetChars(), mthing->x, mthing->y);
 			i = RUNTIME_CLASS(AUnknown);
 		}
 	}
@@ -3743,11 +3742,11 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
 		{
 			if (i->IsDescendantOf (RUNTIME_CLASS(AHealth)))
 				return;
-			if (strcmp (i->Name, "Berserk") == 0)
+			if (i->TypeName == NAME_Berserk)
 				return;
-			if (strcmp (i->Name, "Soulsphere") == 0)
+			if (i->TypeName == NAME_Soulsphere)
 				return;
-			if (strcmp (i->Name, "Megasphere") == 0)
+			if (i->TypeName == NAME_Megasphere)
 				return;
 		}
 		if (dmflags & DF_NO_ITEMS)
@@ -3759,7 +3758,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
 		{
 			if (i->IsDescendantOf (RUNTIME_CLASS(AArmor)))
 				return;
-			if (strcmp (i->Name, "Megasphere") == 0)
+			if (i->TypeName == NAME_Megasphere)
 				return;
 		}
 	}
@@ -3818,7 +3817,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
 // P_SpawnPuff
 //
 
-AActor *P_SpawnPuff (const TypeInfo *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, bool hitthing)
+AActor *P_SpawnPuff (const PClass *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, bool hitthing)
 {
 	AActor *puff;
 
@@ -4226,19 +4225,19 @@ bool P_CheckMissileSpawn (AActor* th)
 //
 //---------------------------------------------------------------------------
 
-AActor *P_SpawnMissile (AActor *source, AActor *dest, const TypeInfo *type)
+AActor *P_SpawnMissile (AActor *source, AActor *dest, const PClass *type)
 {
 	return P_SpawnMissileXYZ (source->x, source->y, source->z + 32*FRACUNIT,
 		source, dest, type);
 }
 
-AActor *P_SpawnMissileZ (AActor *source, fixed_t z, AActor *dest, const TypeInfo *type)
+AActor *P_SpawnMissileZ (AActor *source, fixed_t z, AActor *dest, const PClass *type)
 {
 	return P_SpawnMissileXYZ (source->x, source->y, z, source, dest, type);
 }
 
 AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z,
-	AActor *source, AActor *dest, const TypeInfo *type)
+	AActor *source, AActor *dest, const PClass *type)
 {
 	int defflags3 = GetDefaultByType (type)->flags3;
 
@@ -4315,7 +4314,7 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z,
 //
 //---------------------------------------------------------------------------
 
-AActor *P_SpawnMissileAngle (AActor *source, const TypeInfo *type,
+AActor *P_SpawnMissileAngle (AActor *source, const PClass *type,
 	angle_t angle, fixed_t momz)
 {
 	return P_SpawnMissileAngleZSpeed (source, source->z + 32*FRACUNIT,
@@ -4323,13 +4322,13 @@ AActor *P_SpawnMissileAngle (AActor *source, const TypeInfo *type,
 }
 
 AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z,
-	const TypeInfo *type, angle_t angle, fixed_t momz)
+	const PClass *type, angle_t angle, fixed_t momz)
 {
 	return P_SpawnMissileAngleZSpeed (source, z, type, angle, momz,
 		GetDefaultByType (type)->Speed);
 }
 
-AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const TypeInfo *type)
+AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PClass *type)
 {
 	angle_t an;
 	fixed_t dist;
@@ -4358,7 +4357,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const Typ
 //
 //---------------------------------------------------------------------------
 
-AActor *P_SpawnMissileAngleSpeed (AActor *source, const TypeInfo *type,
+AActor *P_SpawnMissileAngleSpeed (AActor *source, const PClass *type,
 	angle_t angle, fixed_t momz, fixed_t speed)
 {
 	return P_SpawnMissileAngleZSpeed (source, source->z + 32*FRACUNIT,
@@ -4366,7 +4365,7 @@ AActor *P_SpawnMissileAngleSpeed (AActor *source, const TypeInfo *type,
 }
 
 AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z,
-	const TypeInfo *type, angle_t angle, fixed_t momz, fixed_t speed, AActor *owner)
+	const PClass *type, angle_t angle, fixed_t momz, fixed_t speed, AActor *owner)
 {
 	AActor *mo;
 	int defflags3 = GetDefaultByType (type)->flags3;
@@ -4406,18 +4405,18 @@ AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z,
 ================
 */
 
-AActor *P_SpawnPlayerMissile (AActor *source, const TypeInfo *type)
+AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type)
 {
 	return P_SpawnPlayerMissile (source, source->x, source->y, source->z, type, source->angle);
 }
 
-AActor *P_SpawnPlayerMissile (AActor *source, const TypeInfo *type, angle_t angle)
+AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle)
 {
 	return P_SpawnPlayerMissile (source, source->x, source->y, source->z, type, angle);
 }
 
 AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
-							  const TypeInfo *type, angle_t angle)
+							  const PClass *type, angle_t angle)
 {
 	static const int angdiff[3] = { -1<<26, 1<<26, 0 };
 	int i;
@@ -4509,16 +4508,16 @@ bool AActor::IsTeammate (AActor *other)
 //
 //==========================================================================
 
-const TypeInfo *AActor::GetSpecies()
+const PClass *AActor::GetSpecies()
 {
-	const TypeInfo *thistype = GetClass();
+	const PClass *thistype = GetClass();
 
 	if (GetDefaultByType(thistype)->flags3 & MF3_ISMONSTER)
 	{
-		while (thistype->ParentType)
+		while (thistype->ParentClass)
 		{
-			if (GetDefaultByType(thistype->ParentType)->flags3 & MF3_ISMONSTER)
-				thistype = thistype->ParentType;
+			if (GetDefaultByType(thistype->ParentClass)->flags3 & MF3_ISMONSTER)
+				thistype = thistype->ParentClass;
 			else 
 				break;
 		}
diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp
index e74a129ad..aec9d6bbe 100644
--- a/src/p_pspr.cpp
+++ b/src/p_pspr.cpp
@@ -703,7 +703,7 @@ void P_BulletSlope (AActor *mo)
 //
 // P_GunShot
 //
-void P_GunShot (AActor *mo, BOOL accurate, const TypeInfo *pufftype)
+void P_GunShot (AActor *mo, BOOL accurate, const PClass *pufftype)
 {
 	angle_t 	angle;
 	int 		damage;
diff --git a/src/p_pspr.h b/src/p_pspr.h
index 9f144c6bd..8a12d680e 100644
--- a/src/p_pspr.h
+++ b/src/p_pspr.h
@@ -91,7 +91,7 @@ void P_FireWeapon (player_s *player);
 void P_DropWeapon (player_s *player);
 void P_BobWeapon (player_s *player, pspdef_t *psp, fixed_t *x, fixed_t *y);
 void P_BulletSlope (AActor *mo);
-void P_GunShot (AActor *mo, BOOL accurate, const TypeInfo *pufftype);
+void P_GunShot (AActor *mo, BOOL accurate, const PClass *pufftype);
 
 void A_WeaponReady (AActor *actor);
 void A_ReFire (AActor *actor);
diff --git a/src/p_terrain.cpp b/src/p_terrain.cpp
index 0ffd2d335..77ceba454 100644
--- a/src/p_terrain.cpp
+++ b/src/p_terrain.cpp
@@ -557,7 +557,7 @@ static void GenericParse (FGenericParse *parser, const char **keywords,
 	bool notdone = true;
 	int keyword;
 	int val;
-	const TypeInfo *info;
+	const PClass *info;
 
 	do
 	{
@@ -598,7 +598,7 @@ static void GenericParse (FGenericParse *parser, const char **keywords,
 			}
 			else
 			{
-				info = TypeInfo::IFindType (sc_String);
+				info = PClass::FindClass (sc_String);
 				if (!info->IsDescendantOf (RUNTIME_CLASS(AActor)))
 				{
 					Printf ("%s is not an Actor (in %s %s)\n",
@@ -611,7 +611,7 @@ static void GenericParse (FGenericParse *parser, const char **keywords,
 						sc_String, type, name.GetChars());
 				}
 			}
-			SET_FIELD (const TypeInfo *, info);
+			SET_FIELD (const PClass *, info);
 			break;
 
 		case GEN_Splash:
diff --git a/src/p_terrain.h b/src/p_terrain.h
index 5c9a7c620..5654a51a8 100644
--- a/src/p_terrain.h
+++ b/src/p_terrain.h
@@ -49,9 +49,9 @@ struct FSplashDef
 	FName Name;
 	int SmallSplashSound;
 	int NormalSplashSound;
-	const TypeInfo *SmallSplash;
-	const TypeInfo *SplashBase;
-	const TypeInfo *SplashChunk;
+	const PClass *SmallSplash;
+	const PClass *SplashBase;
+	const PClass *SplashChunk;
 	byte ChunkXVelShift;
 	byte ChunkYVelShift;
 	byte ChunkZVelShift;
diff --git a/src/p_things.cpp b/src/p_things.cpp
index e65d3a088..d4ad5bfaa 100644
--- a/src/p_things.cpp
+++ b/src/p_things.cpp
@@ -47,14 +47,14 @@
 #include "templates.h"
 
 // List of spawnable things for the Thing_Spawn and Thing_Projectile specials.
-const TypeInfo *SpawnableThings[MAX_SPAWNABLES];
+const PClass *SpawnableThings[MAX_SPAWNABLES];
 
 static FRandom pr_leadtarget ("LeadTarget");
 
 bool P_Thing_Spawn (int tid, int type, angle_t angle, bool fog, int newtid)
 {
 	int rtn = 0;
-	const TypeInfo *kind;
+	const PClass *kind;
 	AActor *spot, *mobj;
 	FActorIterator iterator (tid);
 
@@ -155,7 +155,7 @@ bool P_Thing_Projectile (int tid, int type, angle_t angle,
 	bool leadTarget)
 {
 	int rtn = 0;
-	const TypeInfo *kind;
+	const PClass *kind;
 	AActor *spot, *mobj, *targ = forcedest;
 	FActorIterator iterator (tid);
 	float fspeed = float(speed);
@@ -369,7 +369,7 @@ CCMD (dumpspawnables)
 	{
 		if (SpawnableThings[i] != NULL)
 		{
-			Printf ("%d %s\n", i, SpawnableThings[i]->Name + 1);
+			Printf ("%d %s\n", i, SpawnableThings[i]->TypeName.GetChars());
 		}
 	}
 }
diff --git a/src/p_user.cpp b/src/p_user.cpp
index 59d6287f1..5489f508d 100644
--- a/src/p_user.cpp
+++ b/src/p_user.cpp
@@ -210,7 +210,7 @@ void APlayerPawn::RemoveInventory (AInventory *item)
 
 bool APlayerPawn::UseInventory (AInventory *item)
 {
-	const TypeInfo *itemtype = item->GetClass();
+	const PClass *itemtype = item->GetClass();
 
 	if (player->cheats & CF_TOTALLYFROZEN)
 	{ // You can't use items if you're totally frozen
@@ -239,7 +239,7 @@ bool APlayerPawn::UseInventory (AInventory *item)
 //
 //===========================================================================
 
-AWeapon *APlayerPawn::BestWeapon (const TypeInfo *ammotype)
+AWeapon *APlayerPawn::BestWeapon (const PClass *ammotype)
 {
 	AWeapon *bestMatch = NULL;
 	int bestOrder = INT_MAX;
@@ -295,7 +295,7 @@ AWeapon *APlayerPawn::BestWeapon (const TypeInfo *ammotype)
 //
 //===========================================================================
 
-AWeapon *APlayerPawn::PickNewWeapon (const TypeInfo *ammotype)
+AWeapon *APlayerPawn::PickNewWeapon (const PClass *ammotype)
 {
 	AWeapon *best = BestWeapon (ammotype);
 
@@ -1148,7 +1148,7 @@ void P_PlayerThink (player_t *player)
 			}
 			else if (cmd->ucmd.upmove > 0 && !(player->cheats & CF_PREDICTING))
 			{
-				AInventory *fly = player->mo->FindInventory (TypeInfo::FindType ("ArtiFly"));
+				AInventory *fly = player->mo->FindInventory (PClass::FindClass (NAME_ArtiFly));
 				if (fly != NULL)
 				{
 					player->mo->UseInventory (fly);
diff --git a/src/thingdef.cpp b/src/thingdef.cpp
index 48272eb09..670c72c55 100644
--- a/src/thingdef.cpp
+++ b/src/thingdef.cpp
@@ -69,7 +69,7 @@
 #include "thingdef.h"
 
 
-const TypeInfo *QuestItemClasses[31];
+const PClass *QuestItemClasses[31];
 
 
 extern TArray<FActorInfo *> Decorations;
@@ -261,7 +261,7 @@ static flagdef WeaponFlags[] =
 	//DEFINE_FLAG(WIF , HITS_GHOSTS, WeaponFlags),	// I think it would be smarter to remap the THRUGHOST flag to this
 };
 
-static const struct { const TypeInfo *Type; flagdef *Defs; int NumDefs; } FlagLists[] =
+static const struct { const PClass *Type; flagdef *Defs; int NumDefs; } FlagLists[] =
 {
 	{ RUNTIME_CLASS(AActor), 		ActorFlags,		sizeof(ActorFlags)/sizeof(flagdef) },
 	{ RUNTIME_CLASS(AInventory), 	InventoryFlags,	sizeof(InventoryFlags)/sizeof(flagdef) },
@@ -303,7 +303,7 @@ static flagdef *FindFlag (flagdef *flags, int numflags, const char *flag)
 	return NULL;
 }
 
-static flagdef *FindFlag (const TypeInfo *type, const char *part1, const char *part2)
+static flagdef *FindFlag (const PClass *type, const char *part1, const char *part2)
 {
 	static bool flagsorted = false;
 	flagdef *def;
@@ -335,7 +335,7 @@ static flagdef *FindFlag (const TypeInfo *type, const char *part1, const char *p
 	{ // Search just the named list
 		for (i = 0; i < NUM_FLAG_LISTS; ++i)
 		{
-			if (stricmp (FlagLists[i].Type->Name+1, part1) == 0)
+			if (stricmp (FlagLists[i].Type->TypeName.GetChars(), part1) == 0)
 			{
 				if (type->IsDescendantOf (FlagLists[i].Type))
 				{
@@ -388,7 +388,7 @@ void A_ChangeFlag(AActor * self)
 	}
 	else
 	{
-		Printf("Unknown flag '%s' in '%s'\n", flagname, self->GetClass()->Name+1);
+		Printf("Unknown flag '%s' in '%s'\n", flagname, self->GetClass()->TypeName.GetChars());
 	}
 }
 
@@ -1015,7 +1015,7 @@ void A_NoBlocking (AActor *actor)
 		{
 			if (di->Name != NAME_None)
 			{
-				const TypeInfo *ti = TypeInfo::IFindType(di->Name);
+				const PClass *ti = PClass::FindClass(di->Name);
 				if (ti) P_DropItem (actor, ti, di->amount, di->probability);
 			}
 			di = di->Next;
@@ -1082,7 +1082,7 @@ static TArray<FState> StateArray;
 
 typedef void (*ActorPropFunction) (AActor *defaults, Baggage &bag);
 
-struct ActorProps { const char *name; ActorPropFunction Handler; const TypeInfo * type; };
+struct ActorProps { const char *name; ActorPropFunction Handler; const PClass * type; };
 
 typedef ActorProps (*ActorPropHandler) (register const char *str, register unsigned int len);
 
@@ -1131,7 +1131,7 @@ static const char * weapon_statenames[]={"SELECT", "DESELECT", "READY", "FIRE",
 static const char * inventory_statenames[]={"USE", "PICKUP", "DROP", NULL };
 
 
-FState ** FindState(AActor * actor, const TypeInfo * type, const char * name)
+FState ** FindState(AActor * actor, const PClass * type, const char * name)
 {
 	int i;
 
@@ -1204,20 +1204,18 @@ static void ResetActor (AActor *actor, Baggage *bag)
 //==========================================================================
 static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
 {
-	char * typeName;
+	FName typeName;
 
 	SC_MustGetString();
 
-	if (TypeInfo::IFindType (sc_String) != NULL)
+	if (PClass::FindClass (sc_String) != NULL)
 	{
 		SC_ScriptError ("Actor %s is already defined.", sc_String);
 	}
 
-	typeName = new char[strlen(sc_String)+2];
-	sprintf(typeName, "A%s", sc_String);
+	typeName = sc_String;
 
-
-	TypeInfo * parent = RUNTIME_CLASS(AActor);
+	PClass * parent = RUNTIME_CLASS(AActor);
 	if (parentc)
 	{
 		*parentc = NULL;
@@ -1225,7 +1223,7 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
 		if (SC_Compare(":"))
 		{
 			SC_MustGetString();
-			parent = const_cast<TypeInfo *> (TypeInfo::IFindType (sc_String));
+			parent = const_cast<PClass *> (PClass::FindClass (sc_String));
 
 			if (parent == NULL)
 			{
@@ -1243,7 +1241,7 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
 		else SC_UnGet();
 	}
 
-	TypeInfo * ti = parent->CreateDerivedClass (typeName, parent->SizeOf);
+	PClass * ti = parent->CreateDerivedClass (typeName, parent->Size);
 	FActorInfo * info = ti->ActorInfo;
 
 	Decorations.Push (info);
@@ -1263,7 +1261,7 @@ static FActorInfo * CreateNewActor(FActorInfo ** parentc, Baggage *bag)
 	if (ti->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
 	{
 		// preinitialize kickback to the default for the game
-		((AWeapon*)(info->Defaults))->Kickback=gameinfo.defKickback;
+		((AWeapon*)(info->Class->Defaults))->Kickback=gameinfo.defKickback;
 	}
 
 	return info;
@@ -1423,7 +1421,7 @@ static void RetargetStatePointers (intptr_t count, const char *target, FState **
 	}
 }
 
-static void RetargetStates (intptr_t count, const char *target, const TypeInfo *cls, AActor *defaults)
+static void RetargetStates (intptr_t count, const char *target, const PClass *cls, AActor *defaults)
 {
 	RetargetStatePointers (count, target, &defaults->SpawnState, &defaults->GreetingsState);
 	if (cls->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
@@ -1793,7 +1791,7 @@ endofstate:
 	}
 	if (count<=minrequiredstate)
 	{
-		SC_ScriptError("A_Jump offset out of range in %s", actor->Class->Name);
+		SC_ScriptError("A_Jump offset out of range in %s", actor->Class->TypeName.GetChars());
 	}
 	return count;
 }
@@ -1804,7 +1802,7 @@ endofstate:
 //
 //==========================================================================
 
-static FState *ResolveGotoLabel (AActor *actor, const TypeInfo *type, char *name)
+static FState *ResolveGotoLabel (AActor *actor, const PClass *type, char *name)
 {
 	FState **stp, *state;
 	char *namestart = name;
@@ -1822,24 +1820,24 @@ static FState *ResolveGotoLabel (AActor *actor, const TypeInfo *type, char *name
 		// superclass, or it may the name of any class that this one derives from.
 		if (stricmp (classname, "Super") == 0)
 		{
-			type = type->ParentType;
+			type = type->ParentClass;
 			actor = GetDefaultByType (type);
 		}
 		else
 		{
-			const TypeInfo *stype = TypeInfo::IFindType (classname);
+			const PClass *stype = PClass::FindClass (classname);
 			if (stype == NULL)
 			{
 				SC_ScriptError ("%s is an unknown class.", classname);
 			}
 			if (!stype->IsDescendantOf (RUNTIME_CLASS(AActor)))
 			{
-				SC_ScriptError ("%s is not an actor class, so it has no states.", stype->Name+1);
+				SC_ScriptError ("%s is not an actor class, so it has no states.", stype->TypeName.GetChars());
 			}
 			if (!stype->IsAncestorOf (type))
 			{
 				SC_ScriptError ("%s is not derived from %s so cannot access its states.",
-					type->Name+1, stype->Name+1);
+					type->TypeName.GetChars(), stype->TypeName.GetChars());
 			}
 			if (type != stype)
 			{
@@ -1869,7 +1867,7 @@ static FState *ResolveGotoLabel (AActor *actor, const TypeInfo *type, char *name
 		}
 		else if (v != 0)
 		{
-			SC_ScriptError ("Attempt to get invalid state from actor %s.", type->Name+1);
+			SC_ScriptError ("Attempt to get invalid state from actor %s.", type->TypeName.GetChars());
 		}
 	}
 	else
@@ -2014,7 +2012,7 @@ static int FinishStates (FActorInfo *actor, AActor *defaults, Baggage &bag)
 // For getting a state address from the parent
 //
 //==========================================================================
-static FState *CheckState(int statenum, TypeInfo *type)
+static FState *CheckState(int statenum, PClass *type)
 {
 	if (SC_GetString() && !sc_Crossed)
 	{
@@ -2024,7 +2022,7 @@ static FState *CheckState(int statenum, TypeInfo *type)
 			SC_MustGetString();
 
 			FState * basestate;
-			FState ** stp=FindState((AActor*)type->ParentType->ActorInfo->Defaults, type, sc_String);
+			FState ** stp=FindState((AActor*)type->ParentClass->Defaults, type, sc_String);
 			int v = 0;
 
 			if (stp) basestate =*stp;
@@ -2052,7 +2050,7 @@ static FState *CheckState(int statenum, TypeInfo *type)
 
 			if (v && !basestate)
 			{
-				SC_ScriptError("Attempt to get invalid state from actor %s\n", type->ParentType->Name+1);
+				SC_ScriptError("Attempt to get invalid state from actor %s\n", type->ParentClass->TypeName.GetChars());
 				return NULL;
 			}
 			return basestate;
@@ -2072,7 +2070,7 @@ static FState *CheckState(int statenum, TypeInfo *type)
 //==========================================================================
 void ParseActorProperties (Baggage &bag)
 {
-	const TypeInfo *info;
+	const PClass *info;
 	const ActorProps *prop;
 
 	ChkBraceOpn ();
@@ -2112,11 +2110,11 @@ void ParseActorProperties (Baggage &bag)
 		{
 			if (!info->IsDescendantOf(prop->type))
 			{
-				SC_ScriptError("\"%s\" requires an actor of type \"%s\"\n", propname.GetChars(), prop->type->Name+1);
+				SC_ScriptError("\"%s\" requires an actor of type \"%s\"\n", propname.GetChars(), prop->type->TypeName.GetChars());
 			}
 			else
 			{
-				prop->Handler ((AActor *)bag.Info->Defaults, bag);
+				prop->Handler ((AActor *)bag.Info->Class->Defaults, bag);
 			}
 		}
 		else
@@ -2142,7 +2140,7 @@ void ProcessActor(void (*process)(FState *, int))
 		FActorInfo * parent;
 
 		info=CreateNewActor(&parent, &bag);
-		defaults=(AActor*)info->Defaults;
+		defaults=(AActor*)info->Class->Defaults;
 		bag.StateSet = false;
 		bag.DropItemSet = false;
 		bag.CurrentState = 0;
@@ -2515,7 +2513,7 @@ static void ActorDropItem (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorSpawnState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Spawn");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Spawn");
 	defaults->SpawnState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2524,7 +2522,7 @@ static void ActorSpawnState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorSeeState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "See");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "See");
 	defaults->SeeState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2533,7 +2531,7 @@ static void ActorSeeState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorMeleeState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Melee");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Melee");
 	defaults->MeleeState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2542,7 +2540,7 @@ static void ActorMeleeState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorMissileState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Missile");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Missile");
 	defaults->MissileState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2551,7 +2549,7 @@ static void ActorMissileState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorPainState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Pain");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Pain");
 	defaults->PainState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2560,7 +2558,7 @@ static void ActorPainState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorDeathState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Death");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Death");
 	defaults->DeathState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2569,7 +2567,7 @@ static void ActorDeathState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorXDeathState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "XDeath");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "XDeath");
 	defaults->XDeathState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2578,7 +2576,7 @@ static void ActorXDeathState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorBurnState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Burn");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Burn");
 	defaults->BDeathState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2587,7 +2585,7 @@ static void ActorBurnState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorIceState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Ice");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Ice");
 	defaults->IDeathState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2596,7 +2594,7 @@ static void ActorIceState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorRaiseState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Raise");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Raise");
 	defaults->RaiseState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2605,7 +2603,7 @@ static void ActorRaiseState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorCrashState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Crash");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Crash");
 	defaults->CrashState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2614,7 +2612,7 @@ static void ActorCrashState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorCrushState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Crush");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Crush");
 	defaults->CrushState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2623,7 +2621,7 @@ static void ActorCrushState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorWoundState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Wound");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Wound");
 	defaults->WoundState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2632,7 +2630,7 @@ static void ActorWoundState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorDisintegrateState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Disintegrate");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Disintegrate");
 	defaults->EDeathState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -2641,7 +2639,7 @@ static void ActorDisintegrateState (AActor *defaults, Baggage &bag)
 //==========================================================================
 static void ActorHealState (AActor *defaults, Baggage &bag)
 {
-	StatePropertyIsDeprecated (bag.Info->Class->Name+1, "Heal");
+	StatePropertyIsDeprecated (bag.Info->Class->TypeName.GetChars(), "Heal");
 	defaults->HealState=CheckState (bag.CurrentState, bag.Info->Class);
 }
 
@@ -3126,7 +3124,7 @@ static void InventoryIcon (AInventory *defaults, Baggage &bag)
 		if (defaults->Icon<=0)
 		{
 			if (bag.Info->GameFilter == GAME_Any || bag.Info->GameFilter & gameinfo.gametype)
-				Printf("Icon '%s' for '%s' not found\n", sc_String, bag.Info->Class->Name+1);
+				Printf("Icon '%s' for '%s' not found\n", sc_String, bag.Info->Class->TypeName.GetChars());
 		}
 	}
 }
@@ -3240,7 +3238,7 @@ static void WeaponAmmoGive2 (AWeapon *defaults, Baggage &bag)
 //
 //==========================================================================
 
-// This class is for storing a name inside a const TypeInfo* field without
+// This class is for storing a name inside a const PClass* field without
 // generating compiler warnings. It does not manipulate data in any other
 // way.
 class fuglyname : public FName
@@ -3248,11 +3246,11 @@ class fuglyname : public FName
 public:
 	fuglyname() : FName() {}
 	fuglyname(const char *foo) : FName(foo) {}
-	operator const TypeInfo *()
+	operator const PClass *()
 	{
-		return reinterpret_cast<const TypeInfo *>(size_t(int(*this)));
+		return reinterpret_cast<const PClass *>(size_t(int(*this)));
 	}
-	fuglyname &operator= (const TypeInfo *foo)
+	fuglyname &operator= (const PClass *foo)
 	{
 		FName *p = this;
 		*p = ENamedName(reinterpret_cast<size_t>(foo));
@@ -3424,18 +3422,18 @@ static void PowerupDuration (APowerupGiver *defaults, Baggage &bag)
 //==========================================================================
 static void PowerupType (APowerupGiver *defaults, Baggage &bag)
 {
-	char typestr[256];
+	FString typestr;
+
 	SC_MustGetString();
-	sc_String[249]=0;
-	sprintf(typestr, "Power%s", sc_String);
-	const TypeInfo * powertype=TypeInfo::FindType(typestr);
+	typestr.Format ("Power%s", sc_String);
+	const PClass * powertype=PClass::FindClass(typestr);
 	if (!powertype)
 	{
-		SC_ScriptError("Unknown powerup type '%s' in '%s'\n", sc_String, bag.Info->Class->Name+1);
+		SC_ScriptError("Unknown powerup type '%s' in '%s'\n", sc_String, bag.Info->Class->TypeName.GetChars());
 	}
 	else if (!powertype->IsDescendantOf(RUNTIME_CLASS(APowerup)))
 	{
-		SC_ScriptError("Invalid powerup type '%s' in '%s'\n", sc_String, bag.Info->Class->Name+1);
+		SC_ScriptError("Invalid powerup type '%s' in '%s'\n", sc_String, bag.Info->Class->TypeName.GetChars());
 	}
 	else
 	{
@@ -3599,9 +3597,9 @@ void FinishThingdef()
 {
 	unsigned int i;
 
-	for (i = 0;i < TypeInfo::m_RuntimeActors.Size(); i++)
+	for (i = 0;i < PClass::m_RuntimeActors.Size(); i++)
 	{
-		TypeInfo * ti = TypeInfo::m_RuntimeActors[i];
+		PClass * ti = PClass::m_RuntimeActors[i];
 
 		// Friendlies never count as kills!
 		if (GetDefaultByType(ti)->flags & MF_FRIENDLY)
@@ -3612,56 +3610,56 @@ void FinishThingdef()
 		// the typeinfo properties of weapons have to be fixed here after all actors have been declared
 		if (ti->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
 		{
-			AWeapon * defaults=(AWeapon *)ti->ActorInfo->Defaults;
+			AWeapon * defaults=(AWeapon *)ti->Defaults;
 			fuglyname v;
 
 			v = defaults->AmmoType1;
 			if (v != NAME_None && v.IsValidName())
 			{
-				defaults->AmmoType1 = TypeInfo::IFindType(v.GetChars());
+				defaults->AmmoType1 = PClass::FindClass(v.GetChars());
 				if (!defaults->AmmoType1)
 				{
-					SC_ScriptError("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->Name+1);
+					SC_ScriptError("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
 				}
-				else if (defaults->AmmoType1->ParentType!=RUNTIME_CLASS(AAmmo))
+				else if (defaults->AmmoType1->ParentClass != RUNTIME_CLASS(AAmmo))
 				{
-					SC_ScriptError("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->Name+1);
+					SC_ScriptError("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
 				}
 			}
 
 			v = defaults->AmmoType2;
 			if (v != NAME_None && v.IsValidName())
 			{
-				defaults->AmmoType2 = TypeInfo::IFindType(v.GetChars());
+				defaults->AmmoType2 = PClass::FindClass(v.GetChars());
 				if (!defaults->AmmoType2)
 				{
-					SC_ScriptError("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->Name+1);
+					SC_ScriptError("Unknown ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
 				}
-				else if (defaults->AmmoType2->ParentType!=RUNTIME_CLASS(AAmmo))
+				else if (defaults->AmmoType2->ParentClass != RUNTIME_CLASS(AAmmo))
 				{
-					SC_ScriptError("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->Name+1);
+					SC_ScriptError("Invalid ammo type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
 				}
 			}
 
 			v = defaults->SisterWeaponType;
 			if (v != NAME_None && v.IsValidName())
 			{
-				defaults->SisterWeaponType = TypeInfo::IFindType(v.GetChars());
+				defaults->SisterWeaponType = PClass::FindClass(v.GetChars());
 				if (!defaults->SisterWeaponType)
 				{
-					SC_ScriptError("Unknown sister weapon type '%s' in '%s'\n", v.GetChars(), ti->Name+1);
+					SC_ScriptError("Unknown sister weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
 				}
 				else if (!defaults->SisterWeaponType->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
 				{
-					SC_ScriptError("Invalid sister weapon type '%s' in '%s'\n", v.GetChars(), ti->Name+1);
+					SC_ScriptError("Invalid sister weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
 				}
 			}
 
 			// Do some consistency checks. If these states are undefined the weapon cannot work!
-			if (!defaults->ReadyState) SC_ScriptError("Weapon %s doesn't define a ready state.\n", ti->Name+1);
-			if (!defaults->UpState) SC_ScriptError("Weapon %s doesn't define a select state.\n", ti->Name+1);
-			if (!defaults->DownState) SC_ScriptError("Weapon %s doesn't define a deselect state.\n", ti->Name+1);
-			if (!defaults->AtkState) SC_ScriptError("Weapon %s doesn't define an attack state.\n", ti->Name+1);
+			if (!defaults->ReadyState) SC_ScriptError("Weapon %s doesn't define a ready state.\n", ti->TypeName.GetChars());
+			if (!defaults->UpState) SC_ScriptError("Weapon %s doesn't define a select state.\n", ti->TypeName.GetChars());
+			if (!defaults->DownState) SC_ScriptError("Weapon %s doesn't define a deselect state.\n", ti->TypeName.GetChars());
+			if (!defaults->AtkState) SC_ScriptError("Weapon %s doesn't define an attack state.\n", ti->TypeName.GetChars());
 
 			// If the weapon doesn't define a hold state use the attack state instead.
 			if (!defaults->HoldAtkState) defaults->HoldAtkState=defaults->AtkState;
@@ -3671,20 +3669,20 @@ void FinishThingdef()
 		// same for the weapon type of weapon pieces.
 		else if (ti->IsDescendantOf(RUNTIME_CLASS(AWeaponPiece)))
 		{
-			AWeaponPiece * defaults=(AWeaponPiece *)ti->ActorInfo->Defaults;
+			AWeaponPiece * defaults=(AWeaponPiece *)ti->Defaults;
 			fuglyname v;
 
 			v = defaults->WeaponClass;
 			if (v != NAME_None)
 			{
-				defaults->WeaponClass = TypeInfo::IFindType(v.GetChars());
+				defaults->WeaponClass = PClass::FindClass(v.GetChars());
 				if (!defaults->WeaponClass)
 				{
-					SC_ScriptError("Unknown weapon type '%s' in '%s'\n", v.GetChars(), ti->Name+1);
+					SC_ScriptError("Unknown weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
 				}
-				else if (defaults->WeaponClass->ParentType!=RUNTIME_CLASS(AWeapon))
+				else if (defaults->WeaponClass->ParentClass != RUNTIME_CLASS(AWeapon))
 				{
-					SC_ScriptError("Invalid weapon type '%s' in '%s'\n", v.GetChars(), ti->Name+1);
+					SC_ScriptError("Invalid weapon type '%s' in '%s'\n", v.GetChars(), ti->TypeName.GetChars());
 				}
 			}
 		}
@@ -3695,6 +3693,6 @@ void FinishThingdef()
 	{
 		char fmt[20];
 		sprintf(fmt, "QuestItem%d", i+1);
-		QuestItemClasses[i]=TypeInfo::IFindType(fmt);
+		QuestItemClasses[i]=PClass::FindClass(fmt);
 	}
 }
diff --git a/src/thingdef_codeptr.cpp b/src/thingdef_codeptr.cpp
index 9ed1084ba..02004a3e0 100644
--- a/src/thingdef_codeptr.cpp
+++ b/src/thingdef_codeptr.cpp
@@ -204,7 +204,7 @@ static void DoAttack (AActor *self, bool domelee, bool domissile)
 	}
 	else if (domissile && MissileName != NAME_None)
 	{
-		const TypeInfo * ti=TypeInfo::IFindType(MissileName);
+		const PClass * ti=PClass::FindClass(MissileName);
 		if (ti) 
 		{
 			// Although there is a P_SpawnMissileZ function its
@@ -416,7 +416,7 @@ void DoJumpIfInventory(AActor * self, AActor * owner)
 	const char * ItemType=(const char *)StateParameters[index];
 	int ItemAmount = EvalExpressionI (StateParameters[index+1], self);
 	int JumpOffset = StateParameters[index+2];
-	const TypeInfo * Type=TypeInfo::FindType(ItemType);
+	const PClass * Type=PClass::FindClass(ItemType);
 
 	if (!Type) return;
 
@@ -526,7 +526,7 @@ void A_CustomMissile(AActor * self)
 
 	if (self->target != NULL || aimmode==2)
 	{
-		const TypeInfo * ti=TypeInfo::FindType(MissileName);
+		const PClass * ti=PClass::FindClass(MissileName);
 		if (ti) 
 		{
 			angle_t ang = (self->angle - ANGLE_90) >> ANGLETOFINESHIFT;
@@ -638,14 +638,14 @@ void A_CustomBulletAttack (AActor *self)
 	int i;
 	int bangle;
 	int bslope;
-	const TypeInfo *pufftype;
+	const PClass *pufftype;
 
 	if (self->target)
 	{
 		A_FaceTarget (self);
 		bangle = self->angle;
 
-		pufftype = TypeInfo::FindType(PuffType);
+		pufftype = PClass::FindClass(PuffType);
 		if (!pufftype) pufftype=RUNTIME_CLASS(ABulletPuff);
 
 		bslope = P_AimLineAttack (self, bangle, MISSILERANGE);
@@ -733,7 +733,7 @@ void A_FireBullets (AActor *self)
 	bool UseAmmo=EvalExpressionN (StateParameters[index+5], self);
 	fixed_t Range=fixed_t(EvalExpressionF (StateParameters[index+6], self) * FRACUNIT);
 	
-	const TypeInfo * PuffType;
+	const PClass * PuffType;
 
 	player_t * player=self->player;
 	AWeapon * weapon=player->ReadyWeapon;
@@ -755,7 +755,7 @@ void A_FireBullets (AActor *self)
 	bangle = self->angle;
 	bslope = bulletpitch;
 
-	PuffType = TypeInfo::FindType(PuffTypeName);
+	PuffType = PClass::FindClass(PuffTypeName);
 	if (!PuffType) PuffType=RUNTIME_CLASS(ABulletPuff);
 
 	S_SoundID (self, CHAN_WEAPON, weapon->AttackSound, 1, ATTN_NORM);
@@ -803,7 +803,7 @@ void A_FireCustomMissile (AActor * self)
 		if (!weapon->DepleteAmmo(weapon->bAltFire, true)) return;	// out of ammo
 	}
 
-	const TypeInfo * ti=TypeInfo::FindType(MissileName);
+	const PClass * ti=PClass::FindClass(MissileName);
 	if (ti) 
 	{
 		angle_t ang = (self->angle - ANGLE_90) >> ANGLETOFINESHIFT;
@@ -847,7 +847,7 @@ void A_CustomPunch (AActor *self)
 	const char * PuffTypeName=(const char *)StateParameters[index+3];
 	fixed_t Range=fixed_t(EvalExpressionF (StateParameters[index+4], self) * FRACUNIT);
 
-	const TypeInfo * PuffType;
+	const PClass * PuffType;
 
 
 	player_t *player=self->player;
@@ -868,7 +868,7 @@ void A_CustomPunch (AActor *self)
 		if (!weapon->DepleteAmmo(weapon->bAltFire, true)) return;	// out of ammo
 	}
 
-	PuffType = TypeInfo::FindType(PuffTypeName);
+	PuffType = PClass::FindClass(PuffTypeName);
 	if (!PuffType) PuffType=RUNTIME_CLASS(ABulletPuff);
 
 	if (Range == 0) Range = MELEERANGE;
@@ -988,7 +988,7 @@ static void DoGiveInventory(AActor * self, AActor * receiver)
 	int amount=EvalExpressionI (StateParameters[index+1], self);
 
 	if (amount==0) amount=1;
-	const TypeInfo * mi=TypeInfo::FindType(item);
+	const PClass * mi=PClass::FindClass(item);
 	if (mi) 
 	{
 		AInventory *item = static_cast<AInventory *>(Spawn (mi, 0, 0, 0));
@@ -1040,7 +1040,7 @@ void DoTakeInventory(AActor * self, AActor * receiver)
 	const char * item =(const char*)StateParameters[index];
 	int amount=EvalExpressionI (StateParameters[index+1], self);
 
-	const TypeInfo * mi=TypeInfo::FindType(item);
+	const PClass * mi=PClass::FindClass(item);
 
 	StateCall.Result=false;
 	if (mi) 
@@ -1083,7 +1083,7 @@ void A_SpawnItem(AActor * self)
 	int index=CheckIndex(4, &CallingState);
 	if (index<0) return;
 
-	const TypeInfo * missile= TypeInfo::FindType((const char *)StateParameters[index]);
+	const PClass * missile= PClass::FindClass((const char *)StateParameters[index]);
 	fixed_t distance = EvalExpressionF (StateParameters[index+1], self);
 	fixed_t zheight = fixed_t(EvalExpressionF (StateParameters[index+2], self) * FRACUNIT);
 	bool useammo = EvalExpressionN (StateParameters[index+3], self);
@@ -1180,7 +1180,7 @@ void A_ThrowGrenade(AActor * self)
 	int index=CheckIndex(5, &CallingState);
 	if (index<0) return;
 
-	const TypeInfo * missile= TypeInfo::FindType((const char *)StateParameters[index]);
+	const PClass * missile= PClass::FindClass((const char *)StateParameters[index]);
 	fixed_t zheight = fixed_t(EvalExpressionF (StateParameters[index+1], self) * FRACUNIT);
 	fixed_t xymom = fixed_t(EvalExpressionF (StateParameters[index+2], self) * FRACUNIT);
 	fixed_t zmom = fixed_t(EvalExpressionF (StateParameters[index+3], self) * FRACUNIT);
@@ -1251,7 +1251,7 @@ void A_SelectWeapon(AActor * actor)
 	int index=CheckIndex(1, NULL);
 	if (index<0 || actor->player == NULL) return;
 
-	const TypeInfo * weapon= TypeInfo::FindType((const char *)StateParameters[index]);
+	const PClass * weapon= PClass::FindClass((const char *)StateParameters[index]);
 	AWeapon * weaponitem = static_cast<AWeapon*>(actor->FindInventory(weapon));
 
 	if (weaponitem != NULL && weaponitem->IsKindOf(RUNTIME_CLASS(AWeapon)))
@@ -1357,12 +1357,12 @@ void A_SpawnDebris(AActor * self)
 {
 	int i;
 	AActor * mo;
-	const TypeInfo * debris;
+	const PClass * debris;
 
 	int index=CheckIndex(1, NULL);
 	if (index<0) return;
 
-	debris = TypeInfo::FindType((const char *)StateParameters[index]);
+	debris = PClass::FindClass((const char *)StateParameters[index]);
 	if (debris == NULL) return;
 
 	for (i = 0; i < GetDefaultByType(debris)->health; i++)
@@ -1454,7 +1454,7 @@ void A_DropInventory(AActor * self)
 {
 	int index=CheckIndex(1, &CallingState);
 	if (index<0) return;
-	const TypeInfo * ti = TypeInfo::FindType((const char*)StateParameters[index]);
+	const PClass * ti = PClass::FindClass((const char*)StateParameters[index]);
 	if (ti)
 	{
 		AInventory * inv = self->FindInventory(ti);
diff --git a/zdoom.vcproj b/zdoom.vcproj
index c6032e954..5b13149c2 100644
--- a/zdoom.vcproj
+++ b/zdoom.vcproj
@@ -569,6 +569,9 @@
 						AdditionalOptions="&quot;  /I /fmod/api/inc&quot;  &quot;  /I /fmod/api/inc&quot;  &quot;  /I /fmod/api/inc&quot;  &quot;  /I /fmod/api/inc&quot;  &quot;  /I /fmod/api/inc&quot;  &quot;  /I /fmod/api/inc&quot;  &quot;  /I /fmod/api/inc&quot;  &quot;  /I /fmod/api/inc&quot; "/>
 				</FileConfiguration>
 			</File>
+			<File
+				RelativePath=".\src\dobjtype.cpp">
+			</File>
 			<File
 				RelativePath=".\src\doomdef.cpp">
 				<FileConfiguration
@@ -1867,6 +1870,9 @@
 			<File
 				RelativePath=".\src\dobject.h">
 			</File>
+			<File
+				RelativePath=".\src\dobjtype.h">
+			</File>
 			<File
 				RelativePath=".\src\doomdata.h">
 			</File>