diff --git a/sp/game/mod_episodic/cfg/skill.cfg b/sp/game/mod_episodic/cfg/skill.cfg
new file mode 100644
index 00000000..ad7b853d
--- /dev/null
+++ b/sp/game/mod_episodic/cfg/skill.cfg
@@ -0,0 +1,256 @@
+// ===========
+//  NPCs
+// ============
+// Barnacle
+sk_barnacle_health		"35"
+
+// Barney
+sk_barney_health		"35"
+
+// Bullseye
+sk_bullseye_health		"35"
+
+// Bullsquid
+//sk_bullsquid_health	"120"
+//sk_bullsquid_dmg_bite	"15"
+//sk_bullsquid_dmg_whip	"25"
+
+// Citizen
+sk_citizen_health		"40"
+
+// Combine Soldier
+sk_combine_s_health		"50"
+sk_combine_s_kick		"10"
+
+// Combine Guard
+sk_combine_guard_health	"70"
+sk_combine_guard_kick	"15"
+
+// strider
+sk_strider_health		"350"
+sk_strider_num_missiles1	"5"
+sk_strider_num_missiles2	"7"
+sk_strider_num_missiles3	"7"
+
+// Headcrab
+sk_headcrab_health		"10"
+sk_headcrab_melee_dmg	"5"
+
+// Fast Headcrab
+sk_headcrab_fast_health	"10"
+
+// Poison Headcrab
+sk_headcrab_poison_health	"35"
+
+// Houndeye
+//sk_houndeye_health		"80"
+//sk_houndeye_dmg_blast	"25"
+
+// Manhack
+sk_manhack_health		"25"
+sk_manhack_melee_dmg	"20"
+
+// Metropolice
+sk_metropolice_health	"40"
+sk_metropolice_stitch_reaction "1.0"
+sk_metropolice_stitch_tight_hitcount "2"
+sk_metropolice_stitch_at_hitcount "1"
+sk_metropolice_stitch_behind_hitcount "3"
+sk_metropolice_stitch_along_hitcount "2"
+
+// Rollermine
+sk_rollermine_shock		"10"
+sk_rollermine_stun_delay "3"
+sk_rollermine_vehicle_intercept "1"
+
+// Scanner (City)
+sk_scanner_health		"30"
+sk_scanner_dmg_dive		"25"
+
+// Stalker
+sk_stalker_health		"50"
+sk_stalker_melee_dmg	"5"
+
+// Vortigaunt
+sk_vortigaunt_health	"100"
+sk_vortigaunt_dmg_claw	"10"
+sk_vortigaunt_dmg_rake	"25"
+sk_vortigaunt_dmg_zap	"50"
+sk_vortigaunt_armor_charge "30"
+
+// Zombie
+sk_zombie_health	"50"
+sk_zombie_dmg_one_slash	"10"
+sk_zombie_dmg_both_slash	"25"
+
+// Poison Zombie
+sk_zombie_poison_health		"175"
+sk_zombie_poison_dmg_spit	"20"
+
+//Antlion
+sk_antlion_health			"30"
+sk_antlion_swipe_damage		"5"
+sk_antlion_jump_damage		"5"
+
+//Antlion Guard
+sk_antlionguard_health		"500"
+sk_antlionguard_dmg_charge	"20"
+sk_antlionguard_dmg_shove	"10"
+
+//Antlion Grub
+//sk_antliongrub_health		"5"
+
+//Ichthyosaur
+sk_ichthyosaur_health		"200"
+sk_ichthyosaur_melee_dmg	"8"
+
+// Combine Gunship
+sk_gunship_burst_size		"15"
+sk_gunship_health_increments	"5"
+sk_npc_dmg_gunship		"40"
+sk_npc_dmg_gunship_to_plr	"3"
+
+// Combine Helicopter
+sk_npc_dmg_helicopter			"6"
+sk_npc_dmg_helicopter_to_plr	"3"
+sk_helicopter_grenadedamage		"30"
+sk_helicopter_grenaderadius		"275"
+sk_helicopter_grenadeforce		"55000"
+
+// Combine Dropship
+sk_npc_dmg_dropship		"2"
+
+// Combine APC
+sk_apc_health				"750"
+
+
+// =================
+//  WEAPONS
+// =================
+
+sk_plr_dmg_ar2			"8"
+sk_npc_dmg_ar2			"3"
+sk_max_ar2				"60"
+sk_max_ar2_altfire		"3"
+
+sk_plr_dmg_alyxgun		"5"
+sk_npc_dmg_alyxgun		"3"
+sk_max_alyxgun			"150"
+
+sk_plr_dmg_pistol		"5"
+sk_npc_dmg_pistol		"3"
+sk_max_pistol			"150"
+
+sk_plr_dmg_smg1			"4"
+sk_npc_dmg_smg1			"3"
+sk_max_smg1				"225"
+
+sk_plr_dmg_buckshot			"8"	
+sk_npc_dmg_buckshot			"3"
+sk_max_buckshot				"30"
+
+sk_plr_dmg_rpg_round		"100"
+sk_npc_dmg_rpg_round		"50"
+sk_max_rpg_round			"3"
+
+sk_plr_dmg_smg1_grenade		"100"
+sk_npc_dmg_smg1_grenade		"50"
+sk_max_smg1_grenade		"3"
+sk_smg1_grenade_radius		"250"
+
+//sk_plr_dmg_gauss			"25"
+//sk_plr_max_dmg_gauss		"30"
+
+sk_plr_dmg_sniper_round		"20"
+sk_npc_dmg_sniper_round		"100"
+sk_max_sniper_round			"30"
+
+sk_plr_dmg_357				"40"
+sk_npc_dmg_357				"30"
+sk_max_357					"12"
+
+sk_plr_dmg_crossbow			"100"
+sk_npc_dmg_crossbow			"10"
+sk_max_crossbow				"10"
+
+sk_plr_dmg_airboat			"3"
+sk_npc_dmg_airboat			"3"
+
+//sk_dmg_sniper_penetrate_plr	"10"
+//sk_dmg_sniper_penetrate_npc	"100"
+
+sk_plr_dmg_grenade			"150"	
+sk_npc_dmg_grenade			"75"
+sk_max_grenade				"5"
+
+sk_plr_dmg_crowbar			"10"
+sk_npc_dmg_crowbar			"5"
+
+sk_plr_dmg_stunstick		"10"
+sk_npc_dmg_stunstick		"40"	// Kill a citizen in one hit
+
+//sk_plr_dmg_satchel			"150"
+//sk_npc_dmg_satchel			"75"
+//sk_satchel_radius			"150"
+
+// Mortar Synth projectile
+//sk_dmg_energy_grenade		"2"
+//sk_energy_grenade_radius	"100"
+
+sk_dmg_homer_grenade		"20"
+sk_homer_grenade_radius		"100"
+
+// Bullsquid spit
+//sk_dmg_spit_grenade			"5"	
+//sk_spit_grenade_radius		"50"
+
+//sk_plr_dmg_tripmine			"150"
+//sk_npc_dmg_tripmine			"125"
+//sk_tripmine_radius			"200"
+
+sk_plr_dmg_fraggrenade 		"125"
+sk_npc_dmg_fraggrenade		"75"
+sk_fraggrenade_radius 		"250"
+
+// HEALTH/SUIT CHARGE DISTRIBUTION
+sk_suitcharger		"75"
+sk_suitcharger_citadel		"500"
+sk_suitcharger_citadel_maxarmor	"200"
+sk_battery			"15"
+sk_healthcharger		"50"
+sk_healthkit		"25"
+sk_healthvial		"10"
+
+// Combine balls
+sk_combineball_seek_angle	"15"
+sk_combineball_guidefactor	"1.0"
+
+// NPC damage adjusters
+sk_npc_head		"3"
+sk_npc_chest	"1"
+sk_npc_stomach	"1"
+sk_npc_arm		"1"
+sk_npc_leg		"1"
+
+// player damage adjusters
+sk_player_head		"3"
+sk_player_chest		"1"
+sk_player_stomach	"1"
+sk_player_arm		"1"
+sk_player_leg		"1"
+
+// Allies
+sk_ally_regen_time	"0.2"
+
+// Jeep
+sk_max_gauss_round	"30"
+
+// =================
+//  RTSL
+// =================
+//Max health
+sk_mechacrab_health "40"
+//Damage inflicted by the mechacrab
+sk_mechacrab_melee_dmg "10"
+//Damage taken by crowbar hits
+sk_mechacrab_crowbar_dmg "20"
\ No newline at end of file
diff --git a/sp/game/mod_episodic/cfg/skill_episodic.cfg b/sp/game/mod_episodic/cfg/skill_episodic.cfg
index 19eedc25..0434d0d5 100644
--- a/sp/game/mod_episodic/cfg/skill_episodic.cfg
+++ b/sp/game/mod_episodic/cfg/skill_episodic.cfg
@@ -7,3 +7,5 @@ sk_apc_missile_damage "50"
 // Antlion air attack
 sk_antlion_air_attack_dmg 	"10"
 
+sk_lostsoul_health		"25"
+sk_lostsoul_melee_dmg	"5"
\ No newline at end of file
diff --git a/sp/game/mod_episodic/halloween.fgd b/sp/game/mod_episodic/halloween.fgd
new file mode 100644
index 00000000..319f5710
--- /dev/null
+++ b/sp/game/mod_episodic/halloween.fgd
@@ -0,0 +1,69 @@
+//=============================================================================
+//
+// Purpose: Half-Life 2 mod game definition file (.fgd) 
+//			Defines new entities for Halloween themed mods
+//
+//=============================================================================
+
+@include "base.fgd"
+@include "halflife2.fgd"
+
+//-------------------------------------------------------------------------
+//
+// NPCs
+//
+//-------------------------------------------------------------------------
+@NPCClass base(BaseNPC) studioprop() = npc_shadow_walker : "Shadow Walker"
+[             
+	additionalequipment(choices) : "Weapons" : "0" : "It is recommended that the Shadow Walker be equipped with a melee weapon such as the crowbar or stunstick. The shotgun and Annabelle also work surprisingly well, but firing patterns have not been set up for automatic weapons." =
+	[
+		"0"  : "Custom Melee Weapon"
+		"weapon_crowbar" : "Crow Bar"
+		"weapon_stunstick" : "Stun Stick"
+		"weapon_shotgun" : "Shotgun"
+		"weapon_annabelle" : "Annabelle"
+		"weapon_pistol" : "Pistol"
+		"weapon_ar2" : "AR2"
+		"weapon_smg1" : "SMG1"
+		"weapon_alyxgun" : "Alyx Gun"
+	]
+	
+	model(studio) : "World Model" : "models/monster/subject.mdl" : "You may specify any model for this NPC. However, the NPC was written with standard human animations in mind. Missing animations may cause errors. Be aware the animations of the model you choose will affect the NPC's behavior."
+	WeaponModel(studio) : "Weapon Model Override" : "models/props_canal/mattpipe.mdl" : "If the Shadow Walker is set to use 'Custom Melee Weapon', you may supply a world model to use. I would recommend using the pipe model, the crowbar model, or the stunstick model."
+	
+	Health(integer) : "Health" : 75 : "Starting health of the NPC."
+	
+	FearSound(sound)		: "Fear Sound" : "NPC_ShadowWalker.Fear" : "The NPC will play this sound when retreating."
+	DeathSound(sound)		: "Death Sound" : "NPC_ShadowWalker.Death" : "The NPC will play this sound on death."
+	IdleSound(sound)		: "Idle Sound" : "NPC_ShadowWalker.Idle" : "The NPC will play this sound while wandering idly."
+	PainSound(sound)		: "Pain Sound" : "NPC_ShadowWalker.Pain" : "The NPC will play this sound when damaged."
+	AlertSound(sound)		: "Alert Sound" : "NPC_ShadowWalker.Alert" : "The NPC will play this sound while in an alert state."
+	LostEnemySound(sound)	: "Lost Enemy Sound" : "NPC_ShadowWalker.LostEnemy" : "The NPC will play this sound if it loses sight of its enemy."
+	FoundEnemySound(sound)	: "Found Enemy Sound" : "NPC_ShadowWalker.FoundEnemy" : "The NPC will play this sound if it finds an enemy again after previously losing it."
+	UseBothSquadSlots(choices) : "Use Both Squad Slots" : 0 : "When in a squad, how many shadow walkers should be able to chase the player at one time? Additional squadmates will run away from the player in the hopes of setting up an ambush." = 
+	[
+		0 : "Use One Squad Slot" 
+		1 : "Use Both Squad Slots" 
+	]
+	CannotOpenDoors(choices) : "Can Open Doors?" : 0 : "Is this NPC able to open doors? You can change this after spawning with EnableOpenDoors and DisableOpenDoors, but it doesn't always seem to work well with pathfinding." = 
+	[
+		0 : "Can Open Doors" 
+		1 : "Cannot Open Doors" 
+	]
+	// // Weapon pickup feature not working yet
+	// CanPickupWeapons(choices) : "Can Pick Up Guns?" : 0 : "Is this NPC able to pick up guns? You can change this after spawning with EnablePickupWeapons and DisablePickupWeapons." = 
+	// [
+	// 	0 : "Cannot Pick Up Guns" 
+	// 	1 : "Can Pick Up Guns" 
+	// ]
+	input SetSpeedModifier(float) : "Set a float value to multiple distance traveled by."
+	input EnableOpenDoors(void) : "Allow this NPC to open doors. (Warning: Doesn't always seem to update pathfinding / AI)"
+	input DisableOpenDoors(void) : "Prevent this NPC from opening doors."
+	// input EnablePickupWeapons(void) : "Allow this NPC to pick up any weapon off of the ground."
+	// input DisablePickupWeapons(void) : "Prevent this NPC from picking up weapons."
+	
+]
+
+@NPCClass base(npc_manhack) studio("models/skeleton/skeleton_torso3.mdl") = npc_lost_soul : "Lost Soul"
+[             
+]
\ No newline at end of file
diff --git a/sp/game/mod_episodic/scripts/game_sounds_manifest.txt b/sp/game/mod_episodic/scripts/game_sounds_manifest.txt
new file mode 100644
index 00000000..4819b6ff
--- /dev/null
+++ b/sp/game/mod_episodic/scripts/game_sounds_manifest.txt
@@ -0,0 +1,126 @@
+game_sounds_manifest
+{
+
+	"precache_file"		"scripts/game_sounds.txt"
+	"precache_file"		"scripts/game_sounds_ui.txt"
+	"precache_file"		"scripts/game_sounds_player.txt"
+
+	// Weapon sounds
+	"precache_file"		"scripts/game_sounds_weapons.txt"
+	"precache_file"		"scripts/game_sounds_weapons_ep2.txt"
+
+	// HL2 World, Ambient Generic, Items, Physics, Vehicles
+	"precache_file"		"scripts/game_sounds_world.txt"
+	"precache_file"		"scripts/game_sounds_ambient_generic.txt"
+	"precache_file"		"scripts/game_sounds_items.txt"
+	"precache_file"		"scripts/game_sounds_physics.txt"
+	"precache_file"		"scripts/game_sounds_vehicles.txt"
+
+	// E3 level sounds
+	"precache_file"		"scripts/level_sounds_e3_c17.txt"
+	"precache_file"		"scripts/level_sounds_e3_town.txt"
+	"precache_file"		"scripts/level_sounds_e3_bugbait.txt"
+
+	// Episodic content sounds
+	"precache_file"		"scripts/npc_sounds_alyx_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_strider_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_strider_episodic2.txt"
+	"precache_file"		"scripts/npc_sounds_turret_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_soldier_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_ministrider_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_roller_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_combine_ball_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_citizen_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_citizen_episodic2.txt"
+	"precache_file"		"scripts/npc_sounds_citizen_ep1.txt"
+	"precache_file"		"scripts/npc_sounds_zombine.txt"
+	"precache_file"		"scripts/npc_sounds_dog_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_antlion_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_antlionguard_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_antlionguard_episodic2.txt"
+	"precache_file"		"scripts/npc_sounds_advisor.txt"
+	"precache_file"		"scripts/npc_sounds_advisor_episodic2.txt"
+	"precache_file"		"scripts/npc_sounds_hunter.txt"
+	"precache_file"		"scripts/npc_sounds_antlion_grub_episodic.txt"
+	"precache_file"		"scripts/npc_sounds_attackheli_episodic2.txt"
+	"precache_file"		"scripts/npc_sounds_fastzombie_episodic2.txt"
+	"precache_file"		"scripts/game_sounds_addendum_ep2.txt"
+
+
+	"precache_file"		"scripts/level_sounds_music_episodic.txt"
+	"precache_file"		"scripts/level_sounds_music_episodic2.txt"
+	"precache_file"		"scripts/game_sounds_weapons_episodic.txt"
+	"precache_file"		"scripts/level_voices_episode_01.txt"
+	"precache_file"		"scripts/level_sounds_aftermath_episodic.txt"
+	"precache_file"		"scripts/level_sounds_outland_episodic.txt"
+	"precache_file"		"scripts/level_sounds_c17_02a.txt"
+
+	"precache_file"		"scripts/level_voices_episode_02.txt"
+	"precache_file"		"scripts/game_sounds_vehicles_ep2.txt"
+
+	// EP2 content sounds
+	"precache_file"		"scripts/game_sounds_physics_ep2.txt"
+
+	// Game level sounds
+	"precache_file"		"scripts/level_sounds_eli_lab.txt"
+	"precache_file"		"scripts/level_sounds_trainyard.txt"
+	"precache_file"		"scripts/level_sounds_k_lab.txt"
+	"precache_file"		"scripts/level_sounds_k_lab2.txt"
+	"precache_file"		"scripts/level_sounds_coast.txt"
+	"precache_file"		"scripts/level_sounds_novaprospekt.txt"
+	"precache_file"		"scripts/level_sounds_streetwar.txt"
+	"precache_file"		"scripts/level_sounds_streetwar2.txt"
+	"precache_file"		"scripts/level_sounds_breencast.txt"
+	"precache_file"		"scripts/level_sounds_citadel.txt"
+	"precache_file"		"scripts/level_sounds_canals.txt"
+	"precache_file"		"scripts/level_sounds_ravenholm.txt"
+	"precache_file"		"scripts/level_sounds_ravenholm2.txt"
+	"precache_file"		"scripts/level_sounds_canals2.txt"
+
+	//Music Tracks
+	"precache_file"		"scripts/level_sounds_music.txt"
+
+	// NPC Sounds
+	"precache_file"		"scripts/npc_sounds_eli.txt"
+	"precache_file"		"scripts/npc_sounds_alyx.txt"
+	"precache_file"		"scripts/npc_sounds_dog.txt"
+	"precache_file"		"scripts/npc_sounds_citizen.txt"
+	"precache_file"		"scripts/npc_sounds_barney.txt"
+	"precache_file"		"scripts/npc_sounds_soldier.txt"
+	"precache_file"		"scripts/npc_sounds_strider.txt"
+	"precache_file"		"scripts/npc_sounds_zombie.txt"
+	"precache_file"		"scripts/npc_sounds_vortigaunt.txt"
+	"precache_file"		"scripts/npc_sounds_turret.txt"
+	"precache_file"		"scripts/npc_sounds_scanner.txt"
+	"precache_file"		"scripts/npc_sounds_rollermine.txt"
+	"precache_file"		"scripts/npc_sounds_poisonzombie.txt"
+	"precache_file"		"scripts/npc_sounds_metropolice.txt"
+   	"precache_file"		"scripts/npc_sounds_combinecamera.txt"
+	"precache_file"		"scripts/npc_sounds_manhack.txt"
+	"precache_file"		"scripts/npc_sounds_ichthyosaur.txt"
+	"precache_file"		"scripts/npc_sounds_blackheadcrab.txt"
+	"precache_file"		"scripts/npc_sounds_fastheadcrab.txt"
+	"precache_file"		"scripts/npc_sounds_headcrab.txt"
+	"precache_file"		"scripts/npc_sounds_fastzombie.txt"
+	"precache_file"		"scripts/npc_sounds_birds.txt"
+	"precache_file"		"scripts/npc_sounds_gunship.txt"
+	"precache_file"		"scripts/npc_sounds_dropship.txt"
+	"precache_file"		"scripts/npc_sounds_barnacle.txt"
+	"precache_file"		"scripts/npc_sounds_attackheli.txt"
+	"precache_file"		"scripts/npc_sounds_antlionguard.txt"
+	"precache_file"		"scripts/npc_sounds_antlion.txt"
+	"precache_file"		"scripts/npc_sounds_env_headcrabcanister.txt"
+	"precache_file"		"scripts/npc_sounds_combine_ball.txt"
+	"precache_file"		"scripts/npc_sounds_combine_mine.txt"
+	"precache_file"		"scripts/npc_sounds_sniper.txt"
+	"precache_file"		"scripts/npc_sounds_stalker.txt"
+	"precache_file"		"scripts/npc_sounds_gman.txt"
+   	"precache_file"		"scripts/npc_sounds_combine_cannon.txt"
+	"precache_file"		"scripts/npc_sounds_alyx_episodic2.txt"
+	"precache_file"		"scripts/npc_sounds_turret_episodic2.txt"
+
+	// 1upD's Halloween NPCs
+	"precache_file"		"scripts/npc_sounds_shadow_walker.txt"
+	"precache_file"		"scripts/npc_sounds_lost_soul.txt"
+	
+}
\ No newline at end of file
diff --git a/sp/game/mod_episodic/scripts/npc_sounds_lost_soul.txt b/sp/game/mod_episodic/scripts/npc_sounds_lost_soul.txt
new file mode 100644
index 00000000..4e1681ef
--- /dev/null
+++ b/sp/game/mod_episodic/scripts/npc_sounds_lost_soul.txt
@@ -0,0 +1,100 @@
+// Default sound scripts for npc_lost_soul
+// Author: 1upD
+
+"NPC_LostSoul.Die"
+{
+	"channel"		"CHAN_BODY"
+	"volume"		"VOL_NORM"
+	"pitch"			"PITCH_NORM"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"wave"			"physics/flesh/flesh_bloody_break.wav"
+}
+
+
+"NPC_LostSoul.Burn"
+{
+	"channel"		"CHAN_ITEM"
+	"volume"		"VOL_NORM"
+	"pitch"			"PITCH_NORM"
+
+	"soundlevel"	"SNDLVL_70dB"
+
+	"rndwave"
+	{
+		"wave"	"player/pl_burnpain1.wav"
+		"wave"	"player/pl_burnpain2.wav"
+		"wave"	"player/pl_burnpain3.wav"
+	}
+}
+
+"NPC_LostSoul.Bat"
+{
+	"channel"		"CHAN_ITEM"
+	"volume"		"VOL_NORM"
+	"pitch"			"150, 175"
+
+	"soundlevel"	"SNDLVL_70dB"
+
+	"wave"			"npc\stalker\stalker_alert3b.wav"
+}
+
+
+"NPC_LostSoul.Float"
+{
+	"channel"		"CHAN_ITEM"
+	"volume"		"VOL_NORM"
+	"pitch"			"PITCH_NORM"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"	"ambient\levels\citadel\datatransfmalevx01.wav"
+		"wave"	"ambient\levels\citadel\datatransmalevx01.wav"
+		"wave"	"ambient\levels\citadel\datatransmalevx02.wav"
+		"wave"	"ambient\levels\citadel\datatransmalevx02.wav"
+		"wave"	"ambient\levels\citadel\datatransrandom03.wav"
+	}
+}
+
+
+"NPC_LostSoul.ChargeAnnounce"
+{
+	"channel"		"CHAN_WEAPON"
+	"volume"		"VOL_NORM"
+	"pitch"			"150, 175"
+	//"pitch"			"120, 125"
+	"soundlevel"	"SNDLVL_70dB"
+	"rndwave"
+	{
+		"wave"	"npc/zombie_poison/pz_alert1.wav"
+		"wave"	"npc/zombie_poison/pz_alert1.wav"
+	}
+}
+
+"NPC_LostSoul.ChargeEnd"
+{
+	"channel"		"CHAN_WEAPON"
+	"volume"		"VOL_NORM"
+	"pitch"			"150, 175"
+	//"pitch"			"120, 125"
+	"soundlevel"	"SNDLVL_70dB"
+	"rndwave"
+	{
+		"wave"	"npc/zombie_poison/pz_warn1.wav"
+		"wave"	"npc/zombie_poison/pz_warn1.wav"
+	}
+}
+
+"NPC_LostSoul.Stunned"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.80"
+	"pitch"			"145,150"
+	"soundlevel"	"SNDLVL_70dB"
+	"wave"			"NPC_Antlion.PoisonBurstScream"
+	
+}
+
diff --git a/sp/game/mod_episodic/scripts/npc_sounds_shadow_walker.txt b/sp/game/mod_episodic/scripts/npc_sounds_shadow_walker.txt
new file mode 100644
index 00000000..f31ef80c
--- /dev/null
+++ b/sp/game/mod_episodic/scripts/npc_sounds_shadow_walker.txt
@@ -0,0 +1,200 @@
+// Default sound scripts for npc_shadow_walker
+// Author: 1upD
+
+"NPC_ShadowWalker.Pain"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"65, 70"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"	"npc\stalker\stalker_pain1.wav"
+		"wave"	"npc\stalker\stalker_pain2.wav"
+		"wave"	"npc\stalker\stalker_pain3.wav"
+
+	}
+}
+
+"NPC_ShadowWalker.Idle"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"80, 90"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"		"npc\stalker\stalker_scream1.wav"
+		"wave"		"npc\stalker\stalker_scream2.wav"
+		"wave"		"npc\stalker\stalker_scream3.wav"
+		"wave"		"npc\stalker\stalker_scream4.wav"
+	}
+}
+
+"NPC_ShadowWalker.Vocal.Idle"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"62, 62"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"	"vo\episode_1\citadel\al_stalk_pleasestopscreaming01.wav"
+		"wave"	"vo\episode_1\citadel\al_stalk_pleasestopscreaming02.wav"
+		"wave"	"vo\episode_1\citadel\al_stalk_pleasestopscreaming03.wav"
+		"wave"	"vo\episode_1\citadel\al_stalk_pleasestopscreaming04.wav"
+		"wave"	"vo\episode_1\citadel\al_stalk_pleasestopscreaming05.wav"
+		"wave"	"vo\k_lab2\al_optimism.wav"
+		"wave"	"vo\episode_1\c17\al_elev_whereselev.wav"
+		"wave"	"vo\episode_1\intro\al_wheredoeshethink.wav"
+		"wave"	"vo\outland_02\griggs_everywhere.wav"
+		"wave"	"vo\outland_11a\silo\kl_silo_wheredata01.wav"
+		"wave"	"vo\episode_1\intro\al_cantbelieveit.wav"
+		"wave"	"vo\episode_1\npc\alyx\al_deaf_canthearanything.wav"
+		"wave"	"vo\episode_1\npc\alyx\al_deaf_canthearyou.wav"
+		"wave"	"vo\k_lab\ba_cantlook.wav"
+
+	}
+}
+
+"NPC_ShadowWalker.Fear"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"62, 62"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		// Replace these
+		"wave"	"npc\stalker\stalker_die2.wav"
+		"wave"	"npc\stalker\stalker_pain1.wav"
+		"wave"	"npc\stalker\stalker_pain2.wav"
+		"wave"	"npc\stalker\stalker_pain3.wav"
+
+	}
+}
+
+"NPC_ShadowWalker.Alert"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"80, 90"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"		"npc\stalker\stalker_alert1b.wav"
+		"wave"		"npc\stalker\stalker_alert2b.wav"
+		"wave"		"npc\stalker\stalker_alert3b.wav"
+	}
+}
+
+"NPC_ShadowWalker.Vocal.Alert"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"62, 62"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"	"vo\citadel\al_bitofit.wav"
+		"wave"	"vo\outland_01\intro\al_rbed_notalone.wav"
+
+	}
+}
+
+"NPC_ShadowWalker.LostEnemy"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"80, 90"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"	"npc\zombie_poison\pz_alert2.wav"
+		"wave"	"npc\stalker\stalker_die2.wav"
+		"wave"	"npc\stalker\stalker_scream4.wav"
+	}
+}
+
+"NPC_ShadowWalker.Vocal.LostEnemy"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"62, 62"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"	"vo\citadel\al_notagain02.wav"
+		"wave"	"vo\episode_1\npc\alyx\al_light_lost05.wav"
+		"wave"	"vo\episode_1\npc\alyx\al_light_lost11.wav"
+		"wave"	"vo\citadel\al_wonderwhere.wav"
+		"wave"	"vo\outland_12a\launch\al_launch_damnit.wav"
+		"wave"	"vo\streetwar\alyx_gate\al_no.wav"
+		"wave"	"vo\k_lab\kl_thenwhere.wav"
+	}
+}
+
+"NPC_ShadowWalker.FoundEnemy"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"75, 85"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"	"npc\stalker\go_alert2.wav"
+		"wave"	"npc\stalker\go_alert2a.wav"
+	}
+}
+
+"NPC_ShadowWalker.Vocal.FoundEnemy"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"62, 62"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"	"npc\stalker\stalker_scream1.wav"
+		"wave"	"vo\citadel\al_thatshim.wav"
+		"wave"	"vo\citadel\al_thereheis.wav"
+		"wave"	"vo\episode_1\npc\alyx\al_rejoin02.wav"
+		"wave"	"vo\episode_1\npc\alyx\al_seemanyfoe03.wav"
+		"wave"	"vo\episode_1\npc\alyx\al_zombie_liveone02.wav"
+
+	}
+}
+
+"NPC_ShadowWalker.Death"
+{
+	"channel"		"CHAN_VOICE"
+	"volume"		"0.95"
+	"pitch"			"60, 65"
+
+	"soundlevel"	"SNDLVL_NORM"
+
+	"rndwave"
+	{
+		"wave"	"ambient\creatures\town_child_scream1.wav"
+	}
+}
\ No newline at end of file
diff --git a/sp/game/mod_episodic/scripts/weapon_custommelee.txt b/sp/game/mod_episodic/scripts/weapon_custommelee.txt
new file mode 100644
index 00000000..5f190461
--- /dev/null
+++ b/sp/game/mod_episodic/scripts/weapon_custommelee.txt
@@ -0,0 +1,22 @@
+// Custom melee weapon - used by npc_shadow_walker for weapon model overrides
+WeaponData
+{
+	// This will be replaced in code
+	"playermodel"			"models/weapons/w_crowbar.mdl"
+
+	"anim_prefix"			"crowbar"
+
+	"clip_size"				"-1"
+	"primary_ammo"			"None"
+	"secondary_ammo"		"None"
+
+	"weight"				"0"
+	"item_flags"			"0"
+
+	// Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds)
+	SoundData
+	{
+		"melee_hit_world"	"Weapon_Crowbar.Melee_HitWorld"
+	}
+
+}
\ No newline at end of file
diff --git a/sp/game/mod_episodic/scripts/weapon_manifest.txt b/sp/game/mod_episodic/scripts/weapon_manifest.txt
new file mode 100644
index 00000000..0e6351bd
--- /dev/null
+++ b/sp/game/mod_episodic/scripts/weapon_manifest.txt
@@ -0,0 +1,24 @@
+weapon_manifest
+{
+	"file"		"scripts/weapon_357.txt"
+	"file"		"scripts/weapon_alyxgun.txt"
+	"file"		"scripts/weapon_annabelle.txt"
+	"file"		"scripts/weapon_ar2.txt"
+	"file"		"scripts/weapon_bugbait.txt"
+	"file"		"scripts/weapon_citizenpackage.txt"
+	"file"		"scripts/weapon_citizensuitcase.txt"
+	"file"		"scripts/weapon_crossbow.txt"
+	"file"		"scripts/weapon_crowbar.txt"
+	"file"		"scripts/weapon_cubemap.txt"
+	"file"		"scripts/weapon_frag.txt"
+	"file"		"scripts/weapon_physcannon.txt"
+	"file"		"scripts/weapon_physgun.txt"
+	"file"		"scripts/weapon_pistol.txt"
+	"file"		"scripts/weapon_rpg.txt"
+	"file"		"scripts/weapon_shotgun.txt"
+	"file"		"scripts/weapon_smg1.txt"
+	"file"		"scripts/weapon_stunstick.txt"
+	
+	// Custom
+	"file"		"scripts/weapon_custommelee.txt"	
+}
\ No newline at end of file
diff --git a/sp/src/game/server/hl2/npc_manhack.cpp b/sp/src/game/server/hl2/npc_manhack.cpp
index feef84f8..f7dd372d 100644
--- a/sp/src/game/server/hl2/npc_manhack.cpp
+++ b/sp/src/game/server/hl2/npc_manhack.cpp
@@ -764,7 +764,7 @@ int	CNPC_Manhack::OnTakeDamage_Alive( const CTakeDamageInfo &info )
 		m_vForceVelocity = vecBestDir * info.GetDamage() * 0.5f;
 		m_flBladeSpeed = 10.0;
 
-		EmitSound( "NPC_Manhack.Bat" );	
+		PlayDamagedSound();
 
 		// tdInfo.SetDamage( 1.0 );
 
@@ -3135,16 +3135,36 @@ void CNPC_Manhack::ShowHostile( bool hostile /*= true*/)
 	//TODO: Open the manhack panels or close them, depending on the state
 	m_bShowingHostile = hostile;
 
-	if ( hostile )
+	PlayAttackSound(hostile);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Play a sound before charging at the player
+// Input  : hostile - 
+//-----------------------------------------------------------------------------
+void CNPC_Manhack::PlayAttackSound(bool hostile /*= true*/)
+{
+	if (hostile)
 	{
-		EmitSound( "NPC_Manhack.ChargeAnnounce" );
+		EmitSound("NPC_Manhack.ChargeAnnounce");
 	}
 	else
 	{
-		EmitSound( "NPC_Manhack.ChargeEnd" );
+		EmitSound("NPC_Manhack.ChargeEnd");
 	}
 }
 
+
+//-----------------------------------------------------------------------------
+// Purpose: Play a sound before charging at the player
+//-----------------------------------------------------------------------------
+void CNPC_Manhack::PlayDamagedSound(void)
+{
+	EmitSound("NPC_Manhack.Bat");
+}
+
+
+
 //-----------------------------------------------------------------------------
 // Purpose: 
 //-----------------------------------------------------------------------------
diff --git a/sp/src/game/server/hl2/npc_manhack.h b/sp/src/game/server/hl2/npc_manhack.h
index 17a3cedb..4554d56c 100644
--- a/sp/src/game/server/hl2/npc_manhack.h
+++ b/sp/src/game/server/hl2/npc_manhack.h
@@ -102,9 +102,11 @@ public:
 
 	virtual float	GetHeadTurnRate( void ) { return 45.0f; } // Degrees per second
 
-	void			CheckCollisions(float flInterval);
+	virtual void	CheckCollisions(float flInterval);
 	virtual void	GatherEnemyConditions( CBaseEntity *pEnemy );
-	void			PlayFlySound(void);
+	virtual void	PlayFlySound(void);
+	virtual void	PlayAttackSound(bool bHostile);
+	virtual void	PlayDamagedSound(void);
 	virtual void	StopLoopingSounds(void);
 
 	void			Precache(void);
@@ -113,9 +115,9 @@ public:
 	void			Activate();
 	void			StartTask( const Task_t *pTask );
 
-	void			BladesInit();
-	void			SoundInit( void );
-	void			StartEye( void );
+	virtual void			BladesInit();
+	virtual void			SoundInit( void );
+	virtual void			StartEye( void );
 	
 	bool			HandleInteraction(int interactionType, void* data, CBaseCombatCharacter* sourceEnt);
 
@@ -126,7 +128,7 @@ public:
 
 	void			SpinBlades(float flInterval);
 
-	void			Slice( CBaseEntity *pHitEntity, float flInterval, trace_t &tr );
+	virtual void	Slice( CBaseEntity *pHitEntity, float flInterval, trace_t &tr );
 	void			Bump( CBaseEntity *pHitEntity, float flInterval, trace_t &tr );
 	void			Splash( const Vector &vecSplashPos );
 
@@ -170,6 +172,7 @@ public:
 		m_iHealth = 0;
 	}
 
+	virtual void SetEyeState(int state);
 
 	DEFINE_CUSTOM_AI;
 
@@ -184,9 +187,8 @@ private:
 	void StopBurst( bool bInterruptSchedule = false );
 
 	void UpdatePanels( void );
-	void SetEyeState( int state );
 
-	void ShowHostile( bool hostile = true );
+
 
 	bool IsFlyingActivity( Activity baseAct );
 
@@ -205,6 +207,7 @@ private:
 	// Are we being held by the physcannon?
 	bool IsHeldByPhyscannon( );
 
+	void ShowHostile(bool hostile = true);
 	void StartLoitering( const Vector &vecLoiterPosition );
 	void StopLoitering() { m_vecLoiterPosition = vec3_invalid; m_fTimeNextLoiterPulse = gpGlobals->curtime; }
 	bool IsLoitering() { return m_vecLoiterPosition != vec3_invalid; }
diff --git a/sp/src/game/server/mod/npc_lost_soul.cpp b/sp/src/game/server/mod/npc_lost_soul.cpp
new file mode 100644
index 00000000..154522a2
--- /dev/null
+++ b/sp/src/game/server/mod/npc_lost_soul.cpp
@@ -0,0 +1,537 @@
+//=//=============================================================================//
+//
+// Purpose: A frightening flying creature with the appearance of a burning skull.
+//		May be familiar to first person shooter fans.
+//
+//		npc_lost_soul is a modified version of a manhack inspired by Mallikas'
+//		HalloweenVilleFour entry, Satanophobia, as well as Doom.
+//
+//	Author: 1upD
+//
+//=============================================================================//
+#include "cbase.h"
+#include "soundenvelope.h"
+#include "npc_manhack.h"
+#include "ai_default.h"
+#include "ai_node.h"
+#include "ai_navigator.h"
+#include "ai_pathfinder.h"
+#include "ai_moveprobe.h"
+#include "ai_memory.h"
+#include "ai_squad.h"
+#include "ai_route.h"
+#include "explode.h"
+#include "basegrenade_shared.h"
+#include "ndebugoverlay.h"
+#include "decals.h"
+#include "gib.h"
+#include "game.h"			
+#include "ai_interactions.h"
+#include "IEffects.h"
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+#include "movevars_shared.h"
+#include "npcevent.h"
+#include "props.h"
+#include "te_effect_dispatch.h"
+#include "ai_squadslot.h"
+#include "world.h"
+#include "smoke_trail.h"
+#include "func_break.h"
+#include "physics_impact_damage.h"
+#include "weapon_physcannon.h"
+#include "physics_prop_ragdoll.h"
+#include "soundent.h"
+#include "ammodef.h"
+#include "EntityFlame.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+ConVar	sk_lostsoul_health("sk_lostsoul_health", "0");
+ConVar	sk_lostsoul_melee_dmg("sk_lostsoul_melee_dmg", "0");
+
+#define MANHACK_NOISEMOD_HIDE 5000
+//=========================================================
+//=========================================================
+class CNPC_LostSoul : public CNPC_Manhack
+{
+	DECLARE_CLASS( CNPC_LostSoul, CNPC_Manhack);
+
+public:
+	void	Precache( void );
+	void	Spawn( void );
+	Class_T Classify( void );
+
+	virtual void	DeathSound(const CTakeDamageInfo &info);
+	virtual bool	ShouldGib(const CTakeDamageInfo &info);
+
+	void			BladesInit();
+	void			SoundInit(void);
+	void			PlayFlySound(void);
+	void			StartEye(void);
+
+
+	void			CheckCollisions(float flInterval);
+
+	void			Slice(CBaseEntity *pHitEntity, float flInterval, trace_t &tr);
+
+	virtual int				OnTakeDamage_Alive(const CTakeDamageInfo &info);
+
+	void Ignite(float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner) { return; }
+
+	// INPCInteractive Functions
+	virtual bool	CanInteractWith(CAI_BaseNPC *pUser) { return false; } // Disabled for now (sjb)
+	virtual	bool	HasBeenInteractedWith() { return false; }
+	virtual void	NotifyInteraction(CAI_BaseNPC *pUser){}
+
+	virtual void	InputPowerdown(inputdata_t &inputdata)
+	{
+		m_iHealth = 0;
+	}
+
+	void			MoveToTarget(float flInterval, const Vector &MoveTarget);
+
+	void PlayAttackSound(bool hostile = true);
+	void PlayDamagedSound(void);
+	void SetEyeState(int state);
+
+	DECLARE_DATADESC();
+
+
+	DEFINE_CUSTOM_AI;
+private:
+	float			m_flNextEngineSoundTime;
+};
+
+
+LINK_ENTITY_TO_CLASS( npc_lost_soul, CNPC_LostSoul );
+IMPLEMENT_CUSTOM_AI( npc_manhack,CNPC_LostSoul );
+
+
+//---------------------------------------------------------
+// Save/Restore
+//---------------------------------------------------------
+BEGIN_DATADESC( CNPC_LostSoul )
+	DEFINE_KEYFIELD(m_iHealth, FIELD_INTEGER, "Health"),
+	
+	DEFINE_FIELD(m_flNextEngineSoundTime, FIELD_TIME)
+END_DATADESC()
+
+//-----------------------------------------------------------------------------
+// Purpose: Initialize the custom schedules
+// Input  :
+// Output :
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::InitCustomSchedules(void) 
+{
+	INIT_CUSTOM_AI(CNPC_LostSoul);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+//
+//
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::Precache( void )
+{
+	PrecacheModel( "models/skeleton/skeleton_torso3.mdl" ); // Replace this with setting from Hammer
+
+	PrecacheScriptSound("NPC_LostSoul.Die");
+	PrecacheScriptSound("NPC_LostSoul.Burn");
+	PrecacheScriptSound("NPC_LostSoul.Float");
+	PrecacheScriptSound("NPC_LostSoul.ChargeAnnounce");
+	PrecacheScriptSound("NPC_LostSoul.ChargeEnd");
+	PrecacheScriptSound("NPC_LostSoul.Stunned");
+	PrecacheScriptSound("NPC_LostSoul.Bat");
+
+	BaseClass::Precache();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+//
+//
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::Spawn( void )
+{
+	BaseClass::Spawn();
+
+	Precache();
+
+	SetModel("models/skeleton/skeleton_torso3.mdl");
+	SetHullType(HULL_TINY_CENTERED); // There was an error being thrown about collision model being smaller than nav hull - need to look into
+	SetHullSizeNormal();
+
+	SetSolid(SOLID_BBOX);
+	AddSolidFlags(FSOLID_NOT_STANDABLE);
+
+	if (HasSpawnFlags(SF_MANHACK_CARRIED))
+	{
+		AddSolidFlags(FSOLID_NOT_SOLID);
+		SetMoveType(MOVETYPE_NONE);
+	}
+	else
+	{
+		SetMoveType(MOVETYPE_VPHYSICS);
+	}
+
+	// Use the convar if health is less than 1
+	if (m_iHealth < 1)
+	{
+		m_iHealth = sk_lostsoul_health.GetFloat();
+	}
+
+	SetViewOffset(Vector(0, 0, 10));		// Position of the eyes relative to NPC's origin.
+	m_flFieldOfView = VIEW_FIELD_FULL;
+	m_NPCState = NPC_STATE_NONE;
+
+	if (m_spawnflags & SF_MANHACK_USE_AIR_NODES)
+	{
+		SetNavType(NAV_FLY);
+	}
+	else
+	{
+		SetNavType(NAV_GROUND);
+	}
+
+	AddEFlags(EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL);
+	AddEffects(EF_NOSHADOW);
+
+	SetBloodColor(BLOOD_COLOR_RED);
+	SetCurrentVelocity(vec3_origin);
+
+	CapabilitiesAdd(bits_CAP_INNATE_MELEE_ATTACK1 | bits_CAP_MOVE_FLY | bits_CAP_SQUAD);
+
+	// Set the noise mod to huge numbers right now, in case this manhack starts out waiting for a script
+	// for instance, we don't want him to bob whilst he's waiting for a script. This allows designers
+	// to 'hide' manhacks in small places. (sjb)
+	SetNoiseMod(MANHACK_NOISEMOD_HIDE, MANHACK_NOISEMOD_HIDE, MANHACK_NOISEMOD_HIDE);
+
+	m_fHeadYaw = 0;
+
+	NPCInit();
+
+	// Manhacks are designed to slam into things, so don't take much damage from it!
+	SetImpactEnergyScale(0.001);
+
+	// Manhacks get 30 seconds worth of free knowledge.
+	GetEnemies()->SetFreeKnowledgeDuration(30.0);
+
+	// don't be an NPC, we want to collide with debris stuff
+	SetCollisionGroup(COLLISION_GROUP_NONE);
+
+	CEntityFlame *pFlame = CEntityFlame::Create(this);
+	if (pFlame)
+	{
+		pFlame->SetLifetime(HUGE_VAL);
+		SetEffectEntity(pFlame);
+		pFlame->SetSize(8);
+		pFlame->SetDamage(0.0f);
+	}
+
+	m_flNextEngineSoundTime = gpGlobals->curtime;
+}
+
+int CNPC_LostSoul::OnTakeDamage_Alive(const CTakeDamageInfo &info)
+{
+	// Don't take burning damage!
+	if (info.GetDamageType() & 8) {
+		return 0;
+	}
+
+	return BaseClass::OnTakeDamage_Alive(info);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::DeathSound(const CTakeDamageInfo &info)
+{
+	CPASAttenuationFilter filter2(this, "NPC_LostSoul.Die");
+	EmitSound(filter2, entindex(), "NPC_LostSoul.Die");
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CNPC_LostSoul::ShouldGib(const CTakeDamageInfo &info)
+{
+	// TODO: Add gibs to lost soul
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Overloads Manhack method. Lost Souls have no blades
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::BladesInit()
+{
+	SetActivity(ACT_FLY);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Overloads manhack engine sound. 
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::SoundInit(void)
+{
+	// Just don't even worry about it.
+}
+
+void CNPC_LostSoul::PlayFlySound(void)
+{
+	float flEnemyDist;
+
+	if (GetEnemy())
+	{
+		flEnemyDist = (GetAbsOrigin() - GetEnemy()->GetAbsOrigin()).Length();
+	}
+	else
+	{
+		flEnemyDist = FLT_MAX;
+	}
+
+	// Play special engine every once in a while
+	if (gpGlobals->curtime > m_flNextEngineSoundTime && flEnemyDist < 48)
+	{
+		m_flNextEngineSoundTime = gpGlobals->curtime + random->RandomFloat(0.5, 2.0);
+
+		EmitSound("NPC_LostSoul.Float");
+	}
+}
+
+void CNPC_LostSoul::StartEye(void)
+{
+	// No eyes
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: We've touched something that we can hurt. Slice it!
+// Input  :
+// Output :
+//-----------------------------------------------------------------------------
+#define MANHACK_SMASH_TIME	0.35		// How long after being thrown from a physcannon that a manhack is eligible to die from impact
+void CNPC_LostSoul::Slice(CBaseEntity *pHitEntity, float flInterval, trace_t &tr)
+{
+	// Don't hurt the player if I'm in water
+	if (GetWaterLevel() > 0 && pHitEntity->IsPlayer())
+		return;
+
+	if (pHitEntity->m_takedamage == DAMAGE_NO)
+		return;
+
+	// Damage must be scaled by flInterval so framerate independent
+	float flDamage = sk_lostsoul_melee_dmg.GetFloat() * flInterval;
+
+	if (pHitEntity->IsPlayer())
+	{
+		flDamage *= 1.0f;
+	}
+
+	if (dynamic_cast<CBreakableProp*>(pHitEntity)) {
+		dynamic_cast<CBreakableProp*>(pHitEntity)->Ignite(10.0f, false);
+	}
+
+	else if (pHitEntity->IsNPC())
+	{
+		dynamic_cast<CAI_BaseNPC*>(pHitEntity)->Ignite(2.0f);
+	}
+
+	if (flDamage < 1.0f)
+	{
+		flDamage = 1.0f;
+	}
+
+	CTakeDamageInfo info(this, this, flDamage, DMG_SLASH);
+
+	// check for actual "ownership" of damage
+	CBasePlayer *pPlayer = HasPhysicsAttacker(MANHACK_SMASH_TIME);
+	if (pPlayer)
+	{
+		info.SetAttacker(pPlayer);
+	}
+
+	Vector dir = (tr.endpos - tr.startpos);
+	if (dir == vec3_origin)
+	{
+		dir = tr.m_pEnt->GetAbsOrigin() - GetAbsOrigin();
+	}
+	CalculateMeleeDamageForce(&info, dir, tr.endpos);
+	pHitEntity->TakeDamage(info);
+
+	// Play burning sound
+	EmitSound("NPC_LostSoul.Burn");
+
+	// Pop back a little bit after hitting the player
+	// ComputeSliceBounceVelocity(pHitEntity, tr);
+
+	// Save off when we last hit something
+	m_flLastDamageTime = gpGlobals->curtime;
+
+	// Reset our state and give the player time to react
+	// StopBurst(true);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input  :
+// Output :
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::MoveToTarget(float flInterval, const Vector &vMoveTarget)
+{
+	if (flInterval <= 0)
+	{
+		return;
+	}
+
+	// -----------------------------------------
+	// Don't steer if engine's have stalled
+	// -----------------------------------------
+	if (m_iHealth <= 0)
+		return;
+
+	if (GetEnemy() != NULL)
+	{
+		TurnHeadToTarget(flInterval, GetEnemy()->EyePosition());
+	}
+	else
+	{
+		TurnHeadToTarget(flInterval, vMoveTarget);
+	}
+
+	// -------------------------------------
+	// Move towards our target
+	// -------------------------------------
+	float	myAccel;
+	float	myZAccel = 300.0f;
+	float	myDecay = 0.3f;
+
+	Vector targetDir;
+	float flDist;
+
+
+		Vector vecCurrentDir = GetCurrentVelocity();
+		VectorNormalize(vecCurrentDir);
+
+		targetDir = vMoveTarget - GetAbsOrigin();
+		flDist = VectorNormalize(targetDir);
+
+		float flDot = DotProduct(targetDir, vecCurrentDir);
+
+		// Otherwise we should steer towards our goal
+		if (flDot > 0.25)
+		{
+			// If my target is in front of me, my flight model is a bit more accurate.
+			myAccel = 300;
+		}
+		else
+		{
+			// Have a harder time correcting my course if I'm currently flying away from my target.
+			myAccel = 200;
+		}
+
+	// Clamp lateral acceleration
+	if (myAccel > (flDist / flInterval))
+	{
+		myAccel = flDist / flInterval;
+	}
+
+	// Clamp vertical movement
+	if (myZAccel > flDist / flInterval)
+	{
+		myZAccel = flDist / flInterval;
+	}
+
+	MoveInDirection(flInterval, targetDir, myAccel, myZAccel, myDecay);
+
+	// calc relative banking targets
+	Vector forward, right;
+	GetVectors(&forward, &right, NULL);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input  :
+// Output :
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::CheckCollisions(float flInterval)
+{
+	// Trace forward to see if I hit anything. But trace forward along the
+	// owner's view direction if you're being carried.
+	Vector vecTraceDir, vecCheckPos;
+	VPhysicsGetObject()->GetVelocity(&vecTraceDir, NULL);
+	vecTraceDir *= flInterval;
+
+	VectorAdd(GetAbsOrigin(), vecTraceDir, vecCheckPos);
+
+	trace_t			tr;
+	CBaseEntity*	pHitEntity = NULL;
+
+	AI_TraceHull(GetAbsOrigin(),
+		vecCheckPos,
+		GetHullMins(),
+		GetHullMaxs(),
+		MoveCollisionMask(),
+		this,
+		COLLISION_GROUP_NONE,
+		&tr);
+
+	if ((tr.fraction != 1.0 || tr.startsolid) && tr.m_pEnt)
+	{
+		PhysicsMarkEntitiesAsTouching(tr.m_pEnt, tr);
+		pHitEntity = tr.m_pEnt;
+
+		if (pHitEntity != NULL &&
+			pHitEntity->m_takedamage == DAMAGE_YES &&
+			pHitEntity->Classify() != CLASS_MANHACK)
+		{
+			// Slice this thing
+			Slice(pHitEntity, flInterval, tr);
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+// Input  : hostile - 
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::PlayAttackSound(bool hostile /*= true*/)
+{
+	if (hostile)
+	{
+		EmitSound("NPC_LostSoul.ChargeAnnounce");
+	}
+	else
+	{
+		EmitSound("NPC_LostSoul.ChargeEnd");
+	}
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::PlayDamagedSound(void)
+{
+	EmitSound("NPC_LostSoul.Bat");
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+// Input  : state - 
+//-----------------------------------------------------------------------------
+void CNPC_LostSoul::SetEyeState(int state)
+{
+	// Do nothing for now
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+//
+//
+// Output : 
+//-----------------------------------------------------------------------------
+Class_T	CNPC_LostSoul::Classify( void )
+{
+	return	CLASS_HEADCRAB;
+}
diff --git a/sp/src/game/server/mod/npc_shadow_walker.cpp b/sp/src/game/server/mod/npc_shadow_walker.cpp
new file mode 100644
index 00000000..730064ec
--- /dev/null
+++ b/sp/src/game/server/mod/npc_shadow_walker.cpp
@@ -0,0 +1,599 @@
+//=//=============================================================================//
+//
+// Purpose: A malevolent being from a parallel universe which at one point
+//		may have been human.		
+//
+//		npc_shadow_walker is designed to be reusable as a generic horror 
+//		game style npc. Its model and sound files may be configured through
+//		the hammer editor using keyfields.
+//
+//	Author: 1upD
+//
+//=============================================================================//
+#include "cbase.h"
+#include "npc_shadow_walker.h"
+#include "ai_hull.h"
+#include "soundent.h"
+#include "game.h"
+#include "npcevent.h"
+#include "engine/IEngineSound.h"
+#include "basehlcombatweapon_shared.h"
+#include "ai_squadslot.h"
+#include "weapon_custom_melee.h"
+
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//---------------------------------------------------------
+// Constants
+//---------------------------------------------------------
+const float MIN_TIME_NEXT_SOUND = 0.5f;
+const float MAX_TIME_NEXT_SOUND = 1.0f;
+const float MIN_TIME_NEXT_FOUNDENEMY_SOUND = 2.0f;
+const float MAX_TIME_NEXT_FOUNDENEMY_SOUND = 5.0f;
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+//
+//
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::Precache( void )
+{
+	// If no model name is supplied, use the default Shadow Walker model
+	if (!GetModelName())
+	{
+		SetModelName(MAKE_STRING("models/monster/subject.mdl"));
+	}
+
+	if (&m_iszWeaponModelName && m_iszWeaponModelName != MAKE_STRING("")) {
+		PrecacheModel(STRING(m_iszWeaponModelName));
+	}
+	else {
+		PrecacheModel("models/props_canal/mattpipe.mdl");
+	}
+
+	PrecacheModel(STRING(GetModelName()));
+	PrecacheNPCSoundScript(&m_iszFearSound, MAKE_STRING("NPC_ShadowWalker.Fear"));
+	PrecacheNPCSoundScript(&m_iszIdleSound, MAKE_STRING("NPC_ShadowWalker.Idle"));
+	PrecacheNPCSoundScript(&m_iszAlertSound, MAKE_STRING("NPC_ShadowWalker.Alert"));
+	PrecacheNPCSoundScript(&m_iszPainSound, MAKE_STRING("NPC_ShadowWalker.Pain"));
+	PrecacheNPCSoundScript(&m_iszLostEnemySound, MAKE_STRING("NPC_ShadowWalker.LostEnemy"));
+	PrecacheNPCSoundScript(&m_iszFoundEnemySound, MAKE_STRING("NPC_ShadowWalker.FoundEnemy"));
+	PrecacheNPCSoundScript(&m_iszDeathSound, MAKE_STRING("NPC_ShadowWalker.Death"));
+
+	m_bWanderToggle = false;
+
+	BaseClass::Precache();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+//
+//
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::Spawn( void )
+{
+	Precache();
+
+	SetModel(STRING(GetModelName()));
+	SetHullType(HULL_HUMAN);
+	SetHullSizeNormal();
+
+	SetSolid( SOLID_BBOX );
+	AddSolidFlags( FSOLID_NOT_STANDABLE );
+	SetMoveType( MOVETYPE_STEP );
+	SetBloodColor( BLOOD_COLOR_RED );
+	
+	// If the health has not been set through Hammer, use a default health value of 75
+	if (m_iHealth < 1) 
+	{
+		m_iHealth = 75;
+	}
+
+	m_flFieldOfView		= 0.5;
+	m_flNextSoundTime = gpGlobals->curtime;
+	m_flNextFoundEnemySoundTime = gpGlobals->curtime;
+	m_NPCState			= NPC_STATE_NONE;
+	m_flSpeedModifier = 1.0f;
+
+	CapabilitiesClear();
+
+	if (!HasSpawnFlags(SF_NPC_START_EFFICIENT))
+	{
+		CapabilitiesAdd(bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD); // The default model has no face animations, but a custom model might
+		CapabilitiesAdd(bits_CAP_SQUAD);
+		CapabilitiesAdd(bits_CAP_USE_WEAPONS | bits_CAP_AIM_GUN | bits_CAP_MOVE_SHOOT);
+		CapabilitiesAdd(bits_CAP_WEAPON_MELEE_ATTACK1 || bits_CAP_WEAPON_MELEE_ATTACK2);
+		CapabilitiesAdd(bits_CAP_DUCK);
+		CapabilitiesAdd(bits_CAP_USE_SHOT_REGULATOR);
+
+		if (!m_bCannotOpenDoors) {
+			CapabilitiesAdd(bits_CAP_DOORS_GROUP);
+		}
+	}
+
+	CapabilitiesAdd(bits_CAP_MOVE_GROUND);
+	SetMoveType(MOVETYPE_STEP);
+
+	NPCInit();
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::FixupWeapon()
+{
+	// If no weapons supplied, give a crowbar
+	CBaseCombatWeapon *pWeapon = GetActiveWeapon();
+	if (pWeapon == NULL) {
+		CWeaponCustomMelee *pMeleeWeapon = (CWeaponCustomMelee*)CreateEntityByName("weapon_custommelee");
+
+		// Apply weapon model override
+		if (&m_iszWeaponModelName && m_iszWeaponModelName != MAKE_STRING("")) {
+			pMeleeWeapon->m_iszWeaponModelName = this->m_iszWeaponModelName;
+		}
+		// Default custom weapon model
+		else {
+			pMeleeWeapon->m_iszWeaponModelName = MAKE_STRING("models/props_canal/mattpipe.mdl");
+		}
+
+		pWeapon = (CBaseCombatWeapon *)pMeleeWeapon;
+
+		DispatchSpawn(pWeapon);
+		Weapon_Equip(pWeapon);
+	}
+
+}
+
+void CNPC_ShadowWalker::Activate()
+{
+	BaseClass::Activate();
+	FixupWeapon();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Choose a schedule after schedule failed
+//-----------------------------------------------------------------------------
+int CNPC_ShadowWalker::SelectFailSchedule(int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode)
+{
+	switch (failedSchedule)
+	{
+	case SCHED_NEW_WEAPON:
+		// If failed trying to pick up a weapon, try again in one second. This is because other AI code
+		// has put this off for 10 seconds under the assumption that the citizen would be able to 
+		// pick up the weapon that they found. 
+		m_flNextWeaponSearchTime = gpGlobals->curtime + 1.0f;
+		break;
+	case SCHED_TAKE_COVER_FROM_ENEMY:
+		// I can't take cover, so I need to run away!
+		return SCHED_RUN_FROM_ENEMY;
+	case SCHED_CHASE_ENEMY:
+		// I can't run towards the enemy, so I will just run randomly!
+		return SCHED_CHASE_ENEMY_FAILED;
+	case SCHED_RUN_FROM_ENEMY:
+		// I can't run away, so I will just run randomly!
+		return SCHED_RUN_RANDOM;
+	case SCHED_INVESTIGATE_SOUND:
+		// I can't investigate a sound I heard.
+		return SCHED_IDLE_WANDER;
+	}
+
+	return BaseClass::SelectFailSchedule(failedSchedule, failedTask, taskFailCode);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Select a schedule to retrieve better weapons if they are available.
+//-----------------------------------------------------------------------------
+int CNPC_ShadowWalker::SelectScheduleRetrieveItem()
+{
+	if (m_bCanPickupWeapons && HasCondition(COND_BETTER_WEAPON_AVAILABLE))
+	{
+		CBaseHLCombatWeapon *pWeapon = dynamic_cast<CBaseHLCombatWeapon *>(Weapon_FindUsable(WEAPON_SEARCH_DELTA));
+		if (pWeapon)
+		{
+			m_flNextWeaponSearchTime = gpGlobals->curtime + 10.0;
+			// Now lock the weapon for several seconds while we go to pick it up.
+			pWeapon->Lock(10.0, this);
+			SetTarget(pWeapon);
+			return SCHED_NEW_WEAPON;
+		}
+	}
+
+	return SCHED_NONE;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Select a schedule to retrieve better weapons if they are available.
+//-----------------------------------------------------------------------------
+int CNPC_ShadowWalker::SelectScheduleWander()
+{
+	m_bWanderToggle = !m_bWanderToggle;
+	if (m_bWanderToggle) {
+		return SCHED_IDLE_WANDER;
+	}
+	else {
+		return SCHED_NONE;
+	}
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Select a schedule to execute based on conditions. 
+// This is the most critical AI method.
+//-----------------------------------------------------------------------------
+int CNPC_ShadowWalker::SelectSchedule()
+{
+	switch (m_NPCState)
+	{
+	case NPC_STATE_IDLE:
+		AssertMsgOnce(GetEnemy() == NULL, "NPC has enemy but is not in combat state?");
+		return SelectIdleSchedule();
+
+	case NPC_STATE_ALERT:
+		AssertMsgOnce(GetEnemy() == NULL, "NPC has enemy but is not in combat state?");
+		return SelectAlertSchedule();
+
+	case NPC_STATE_COMBAT:
+		return SelectCombatSchedule();
+
+	default:
+		return BaseClass::SelectSchedule();
+	}
+}
+
+//-----------------------------------------------------------------------------
+// Idle schedule selection
+//-----------------------------------------------------------------------------
+int CNPC_ShadowWalker::SelectIdleSchedule()
+{
+	int nSched = SelectFlinchSchedule();
+	if (nSched != SCHED_NONE)
+		return nSched;
+
+	if (HasCondition(COND_HEAR_DANGER) ||
+		HasCondition(COND_HEAR_COMBAT) ||
+		HasCondition(COND_HEAR_WORLD) ||
+		HasCondition(COND_HEAR_BULLET_IMPACT) ||
+		HasCondition(COND_HEAR_PLAYER))
+	{
+		// Investigate sound source
+		return SCHED_INVESTIGATE_SOUND;
+	}
+
+	nSched = SelectScheduleRetrieveItem();
+	if (nSched != SCHED_NONE)
+		return nSched;
+
+	// no valid route! Wander instead
+	if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) {
+		nSched = SelectScheduleWander();
+		if (nSched != SCHED_NONE)
+			return nSched;
+		return SCHED_IDLE_STAND;
+	}
+
+	// valid route. Get moving
+	return SCHED_IDLE_WALK;
+}
+
+//-----------------------------------------------------------------------------
+// Alert schedule selection
+//-----------------------------------------------------------------------------
+int CNPC_ShadowWalker::SelectAlertSchedule()
+{
+	// Per default base NPC, check flinch schedule first
+	int nSched = SelectFlinchSchedule();
+	if (nSched != SCHED_NONE)
+		return nSched;
+
+	// Scan around for new enemies
+	if (HasCondition(COND_ENEMY_DEAD) && SelectWeightedSequence(ACT_VICTORY_DANCE) != ACTIVITY_NOT_AVAILABLE)
+		return SCHED_ALERT_SCAN;
+
+	if (HasCondition(COND_HEAR_DANGER) ||
+		HasCondition(COND_HEAR_PLAYER) ||
+		HasCondition(COND_HEAR_WORLD) ||
+		HasCondition(COND_HEAR_BULLET_IMPACT) ||
+		HasCondition(COND_HEAR_COMBAT))
+	{
+		// Investigate sound source
+		AlertSound();
+		return SCHED_INVESTIGATE_SOUND;
+	}
+
+	nSched = SelectScheduleRetrieveItem();
+	if (nSched != SCHED_NONE)
+		return nSched;
+
+	// no valid route! Wander instead
+	if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) {
+		nSched = SelectScheduleWander();
+		if (nSched != SCHED_NONE)
+			return nSched;
+		return SCHED_IDLE_STAND;
+	}
+
+	// valid route. Get moving
+	return SCHED_ALERT_WALK;
+}
+
+//-----------------------------------------------------------------------------
+// Combat schedule selection
+//-----------------------------------------------------------------------------
+int CNPC_ShadowWalker::SelectCombatSchedule()
+{
+	// Check flinch first
+	int nSched = SelectFlinchSchedule();
+	if (nSched != SCHED_NONE)
+		return nSched;
+
+	// Check enemy death
+	if (HasCondition(COND_ENEMY_DEAD))
+	{
+		// clear the current (dead) enemy and try to find another.
+		SetEnemy(NULL);
+
+		if (ChooseEnemy())
+		{
+			FoundEnemySound();
+
+			ClearCondition(COND_ENEMY_DEAD);
+			return SelectSchedule();
+		}
+
+		SetState(NPC_STATE_ALERT);
+		return SelectSchedule();
+	}
+
+	// Can any enemies see me?
+	bool bEnemyCanSeeMe = HasCondition(COND_SEE_ENEMY) && HasCondition(COND_ENEMY_FACING_ME) && HasCondition(COND_HAVE_ENEMY_LOS);
+
+
+	// If I'm scared of this enemy and he's looking at me, run away
+	if ((IRelationType(GetEnemy()) == D_FR) && bEnemyCanSeeMe)
+	{
+			FearSound();
+			return SCHED_RUN_FROM_ENEMY;
+	}
+
+	// If in a squad, only one or two shadow walkers can chase the player. This is configurable through Hammer.
+	bool bCanChase = true;
+	if (bEnemyCanSeeMe && m_bUseBothSquadSlots) {
+		bCanChase = OccupyStrategySlotRange(SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2);
+	}
+	else if (bEnemyCanSeeMe){
+		bCanChase = OccupyStrategySlot(SQUAD_SLOT_ATTACK1);
+	}
+
+	// If I'm not allowed to chase this enemy of this enemy and he's looking at me, set up an ambush
+	if (!bCanChase)
+	{
+		FearSound();
+		return SCHED_HIDE;
+		
+	}
+
+	// Reloading conditions are necessary just in case for some reason somebody gives the Shadow Walker a gun
+	if (HasRangedWeapon() && (HasCondition(COND_LOW_PRIMARY_AMMO) || HasCondition(COND_NO_PRIMARY_AMMO)))
+	{
+		return SCHED_HIDE_AND_RELOAD;
+	}
+
+	// Can we see the enemy?
+	if (!HasCondition(COND_SEE_ENEMY))
+	{
+		// Chase!
+		return SCHED_CHASE_ENEMY;
+	}
+
+	if (HasCondition(COND_TOO_CLOSE_TO_ATTACK))
+		return SCHED_BACK_AWAY_FROM_ENEMY;
+
+
+	// we can see the enemy
+	if (HasCondition(COND_CAN_MELEE_ATTACK1)) {
+			return SCHED_MELEE_ATTACK1;
+	}
+
+	if (HasCondition(COND_CAN_MELEE_ATTACK2)) {
+			return SCHED_MELEE_ATTACK2;
+	}
+
+	if (HasRangedWeapon() && GetShotRegulator()->IsInRestInterval())
+	{
+		if (HasCondition(COND_CAN_RANGE_ATTACK1))
+			return SCHED_COMBAT_FACE;
+	}
+
+	if (HasRangedWeapon() && HasCondition(COND_CAN_RANGE_ATTACK1))
+	{
+		if (OccupyStrategySlotRange(SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2))
+			return SCHED_RANGE_ATTACK1;
+		return SCHED_RUN_FROM_ENEMY;
+	}
+
+	if (HasRangedWeapon() && HasCondition(COND_CAN_RANGE_ATTACK2))
+		return SCHED_RANGE_ATTACK2;
+
+
+	if (HasCondition(COND_NOT_FACING_ATTACK))
+		return SCHED_COMBAT_FACE;
+
+	if (!HasCondition(COND_CAN_RANGE_ATTACK1) && !HasCondition(COND_CAN_MELEE_ATTACK1))
+	{
+		// if we can see enemy but can't use either attack type, we must need to get closer to enemy
+		if (HasRangedWeapon())
+			return SCHED_MOVE_TO_WEAPON_RANGE;
+
+		return SCHED_CHASE_ENEMY;
+	}
+
+	DevWarning(2, "No suitable combat schedule!\n");
+	return SCHED_FAIL;
+}
+
+bool CNPC_ShadowWalker::HasRangedWeapon()
+{
+	CBaseCombatWeapon *pWeapon = GetActiveWeapon();
+
+	if (pWeapon)
+		return !(FClassnameIs(pWeapon, "weapon_crowbar") || FClassnameIs(pWeapon, "weapon_stunstick") || FClassnameIs(pWeapon, "weapon_custommelee"));
+
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Override base class schedules
+//-----------------------------------------------------------------------------
+int CNPC_ShadowWalker::TranslateSchedule(int scheduleType)
+{
+	switch (scheduleType)
+	{
+	case SCHED_MELEE_ATTACK1:
+		return SCHED_MELEE_ATTACK_NOINTERRUPT;
+	case SCHED_IDLE_WANDER: // We want idle wandering to be interruptible - patrol walk is a better schedule
+		return SCHED_PATROL_WALK;
+	}
+
+	return BaseClass::TranslateSchedule(scheduleType);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Override base class activiites
+//-----------------------------------------------------------------------------
+Activity CNPC_ShadowWalker::NPC_TranslateActivity(Activity activity)
+{
+	switch (activity) {
+	case ACT_RUN_AIM_SHOTGUN:
+		return ACT_RUN_AIM_RIFLE;
+	case ACT_WALK_AIM_SHOTGUN:
+		return ACT_WALK_AIM_RIFLE;
+	case ACT_IDLE_ANGRY_SHOTGUN:
+		return ACT_IDLE_ANGRY_SMG1;
+	case ACT_RANGE_ATTACK_SHOTGUN_LOW:
+		return ACT_RANGE_ATTACK_SMG1_LOW;
+	case ACT_IDLE_MELEE:
+	case ACT_IDLE_ANGRY_MELEE:  // If the walker has a melee weapon but is in an idle state, don't raise the weapon
+		if (m_NPCState == NPC_STATE_IDLE)
+			return ACT_IDLE_SUITCASE;
+	default:
+		return BaseClass::NPC_TranslateActivity(activity);
+	}
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Play sound when an enemy is spotted. This sound has a separate
+//	timer from other sounds to prevent looping if the NPC gets caught
+//	in a 'found enemy' condition.
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::FoundEnemySound(void)
+{
+	if (gpGlobals->curtime > m_flNextFoundEnemySoundTime)
+	{
+		m_flNextFoundEnemySoundTime = gpGlobals->curtime + random->RandomFloat(MIN_TIME_NEXT_FOUNDENEMY_SOUND, MAX_TIME_NEXT_FOUNDENEMY_SOUND);
+		PlaySound(m_iszFoundEnemySound, true);
+	}
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Play NPC soundscript
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::PlaySound(string_t soundname, bool required /*= false */)
+{
+	// TODO: Check if silent
+	if (required || gpGlobals->curtime > m_flNextSoundTime)
+	{
+		m_flNextSoundTime = gpGlobals->curtime + random->RandomFloat(MIN_TIME_NEXT_SOUND, MAX_TIME_NEXT_SOUND);
+		//CPASAttenuationFilter filter2(this, STRING(soundname));
+		EmitSound(STRING(soundname));
+	}
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Assign a default soundscript if none is provided, then precache
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::PrecacheNPCSoundScript(string_t * SoundName, string_t defaultSoundName) 
+{
+	if (!SoundName) {
+		*SoundName = defaultSoundName;
+	}
+	PrecacheScriptSound(STRING(*SoundName));
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get movement speed, multipled by modifier
+//-----------------------------------------------------------------------------
+float CNPC_ShadowWalker::GetSequenceGroundSpeed(CStudioHdr *pStudioHdr, int iSequence)
+{
+	float t = SequenceDuration(pStudioHdr, iSequence);
+
+	if (t > 0)
+	{
+		return (GetSequenceMoveDist(pStudioHdr, iSequence) * m_flSpeedModifier / t);
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Hammer input to change the speed of the NPC
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::InputSetSpeedModifier(inputdata_t &inputdata)
+{
+	this->m_flSpeedModifier = inputdata.value.Float();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Hammer input to enable opening doors
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::InputEnableOpenDoors(inputdata_t &inputdata)
+{
+	m_bCannotOpenDoors = false;
+	if (!HasSpawnFlags(SF_NPC_START_EFFICIENT))
+	{
+		CapabilitiesAdd(bits_CAP_DOORS_GROUP);
+	}
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Hammer input to enable opening doors
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::InputDisableOpenDoors(inputdata_t &inputdata)
+{
+	m_bCannotOpenDoors = true;
+	if (!HasSpawnFlags(SF_NPC_START_EFFICIENT))
+	{
+		CapabilitiesRemove(bits_CAP_DOORS_GROUP);
+	}
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Hammer input to enable weapon pickup behavior
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::InputEnablePickupWeapons(inputdata_t &inputdata)
+{
+	m_bCanPickupWeapons = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Hammer input to enable weapon pickup behavior
+//-----------------------------------------------------------------------------
+void CNPC_ShadowWalker::InputDisablePickupWeapons(inputdata_t &inputdata)
+{
+	m_bCanPickupWeapons = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: 
+//
+//
+// Output : 
+//-----------------------------------------------------------------------------
+Class_T	CNPC_ShadowWalker::Classify( void )
+{
+	return	CLASS_ZOMBIE;
+}
diff --git a/sp/src/game/server/mod/npc_shadow_walker.h b/sp/src/game/server/mod/npc_shadow_walker.h
new file mode 100644
index 00000000..82f8bea9
--- /dev/null
+++ b/sp/src/game/server/mod/npc_shadow_walker.h
@@ -0,0 +1,179 @@
+//=//=============================================================================//
+//
+// Purpose: A malevolent being from a parallel universe which at one point
+//		may have been human.		
+//
+//		npc_shadow_walker is designed to be reusable as a generic horror 
+//		game style npc. Its model and sound files may be configured through
+//		the hammer editor using keyfields.
+//
+//	Author: 1upD
+//
+//=============================================================================//
+#include "cbase.h"
+#include "ai_default.h"
+#include "ai_task.h"
+#include "ai_schedule.h"
+#include "entitylist.h"
+#include "activitylist.h"
+#include "ai_basenpc.h"
+#include "ai_blended_movement.h"
+#include "ai_behavior_actbusy.h"
+
+//=========================================================
+// schedules
+//=========================================================
+enum
+{
+	SCHED_MELEE_ATTACK_NOINTERRUPT = LAST_SHARED_SCHEDULE,
+	SCHED_HIDE,
+
+	LAST_SHADOW_WALKER_SCHED
+};
+
+//=========================================================
+//=========================================================
+typedef CAI_BlendingHost< CAI_BehaviorHost<CAI_BaseNPC> > CAI_CustomNPCBase;
+
+class CNPC_ShadowWalker : public CAI_CustomNPCBase
+{
+	DECLARE_CLASS(CNPC_ShadowWalker, CAI_CustomNPCBase);
+
+public:
+	void				Precache(void);
+	void				Spawn(void);
+	Class_T				Classify(void);
+	virtual int			SelectFailSchedule(int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode);
+	virtual int 		SelectScheduleRetrieveItem();
+	virtual int 		SelectScheduleWander();
+	virtual int 		SelectSchedule();
+	virtual int			SelectIdleSchedule();
+	virtual int			SelectAlertSchedule();
+	virtual int			SelectCombatSchedule();
+	virtual float		GetSequenceGroundSpeed(CStudioHdr *pStudioHdr, int iSequence);
+	virtual Activity	NPC_TranslateActivity(Activity eNewActivity);
+	virtual int			TranslateSchedule(int scheduleType);
+
+	// Sounds
+	virtual void		PlaySound(string_t soundname, bool optional);
+	virtual void		DeathSound(const CTakeDamageInfo &info) { PlaySound(m_iszDeathSound, true); }
+	virtual void		AlertSound(void) { PlaySound(m_iszAlertSound, false); };
+	virtual void		IdleSound(void) { PlaySound(m_iszIdleSound, false); };
+	virtual void		PainSound(const CTakeDamageInfo &info) { PlaySound(m_iszPainSound, true); };
+	virtual void		FearSound(void) { PlaySound(m_iszFearSound, false); };
+	virtual void		LostEnemySound(void) { PlaySound(m_iszLostEnemySound, false); };
+	virtual void		FoundEnemySound(void);
+
+	void				Activate();
+	void				FixupWeapon();
+
+	// Inputs
+	virtual void		InputSetSpeedModifier(inputdata_t &inputdata);
+	virtual void		InputEnableOpenDoors(inputdata_t &inputdata);
+	virtual void		InputDisableOpenDoors(inputdata_t &inputdata);
+	virtual void		InputEnablePickupWeapons(inputdata_t &inputdata);
+	virtual void		InputDisablePickupWeapons(inputdata_t &inputdata);
+
+	DECLARE_DATADESC();
+
+	string_t			m_iszWeaponModelName;			// Path/filename of model to override weapon model.
+
+	string_t			m_iszFearSound;			// Path/filename of WAV file to play.
+	string_t			m_iszDeathSound;			// Path/filename of WAV file to play.
+	string_t			m_iszIdleSound;			// Path/filename of WAV file to play.
+	string_t			m_iszPainSound;			// Path/filename of WAV file to play.
+	string_t			m_iszAlertSound;			// Path/filename of WAV file to play.
+	string_t			m_iszLostEnemySound;		// Path/filename of WAV file to play.
+	string_t			m_iszFoundEnemySound;		// Path/filename of WAV file to play.
+
+	DEFINE_CUSTOM_AI;
+
+private:
+	bool				HasRangedWeapon();
+	void				PrecacheNPCSoundScript(string_t* SoundName, string_t defaultSoundName);
+
+
+	bool				m_bUseBothSquadSlots;	// If true use two squad slots, if false use one squad slot
+	bool				m_bCannotOpenDoors;		// If true, this NPC cannot open doors. The condition is reversed because originally it could.
+	bool				m_bCanPickupWeapons;			// If true, this NPC is able to pick up weapons off of the ground just like npc_citizen.
+	bool				m_bWanderToggle;		// Boolean to toggle wandering / standing every think cycle
+	float				m_flNextSoundTime;		// Next time at which this NPC is allowed to play an NPC sound
+	float				m_flNextFoundEnemySoundTime;	// Next time at which this NPC is allowed to play an NPC sound
+	float				m_flSpeedModifier;		// Modifier to apply to move distance
+};
+
+
+LINK_ENTITY_TO_CLASS(npc_shadow_walker, CNPC_ShadowWalker);
+
+//---------------------------------------------------------
+// Save/Restore
+//---------------------------------------------------------
+BEGIN_DATADESC(CNPC_ShadowWalker)
+DEFINE_KEYFIELD(m_iszWeaponModelName, FIELD_STRING, "WeaponModel"),
+DEFINE_KEYFIELD(m_iHealth, FIELD_INTEGER, "Health"),
+DEFINE_KEYFIELD(m_iszFearSound, FIELD_SOUNDNAME, "FearSound"),
+DEFINE_KEYFIELD(m_iszDeathSound, FIELD_SOUNDNAME, "DeathSound"),
+DEFINE_KEYFIELD(m_iszIdleSound, FIELD_SOUNDNAME, "IdleSound"),
+DEFINE_KEYFIELD(m_iszPainSound, FIELD_SOUNDNAME, "PainSound"),
+DEFINE_KEYFIELD(m_iszAlertSound, FIELD_SOUNDNAME, "AlertSound"),
+DEFINE_KEYFIELD(m_iszLostEnemySound, FIELD_SOUNDNAME, "LostEnemySound"),
+DEFINE_KEYFIELD(m_iszFoundEnemySound, FIELD_SOUNDNAME, "FoundEnemySound"),
+DEFINE_KEYFIELD(m_bUseBothSquadSlots, FIELD_BOOLEAN, "UseBothSquadSlots"),
+DEFINE_KEYFIELD(m_bCannotOpenDoors, FIELD_BOOLEAN, "CannotOpenDoors"),
+DEFINE_KEYFIELD(m_bCanPickupWeapons, FIELD_BOOLEAN, "CanPickupWeapons"),
+
+DEFINE_FIELD(m_bWanderToggle, FIELD_BOOLEAN),
+DEFINE_FIELD(m_flNextSoundTime, FIELD_TIME),
+DEFINE_FIELD(m_flNextFoundEnemySoundTime, FIELD_TIME),
+DEFINE_FIELD(m_flSpeedModifier, FIELD_TIME),
+
+DEFINE_INPUTFUNC(FIELD_FLOAT, "SetSpeedModifier", InputSetSpeedModifier),
+DEFINE_INPUTFUNC(FIELD_VOID, "EnableOpenDoors", InputEnableOpenDoors),
+DEFINE_INPUTFUNC(FIELD_VOID, "DisableOpenDoors", InputDisableOpenDoors),
+DEFINE_INPUTFUNC(FIELD_VOID, "EnablePickupWeapons", InputEnablePickupWeapons),
+DEFINE_INPUTFUNC(FIELD_VOID, "DisablePickupWeapons", InputDisablePickupWeapons)
+END_DATADESC()
+
+
+AI_BEGIN_CUSTOM_NPC(npc_shadow_walker, CNPC_ShadowWalker)
+//=========================================================
+// > Melee_Attack_NoInterrupt
+//=========================================================
+DEFINE_SCHEDULE
+(
+	SCHED_MELEE_ATTACK_NOINTERRUPT,
+
+	"	Tasks"
+	"		TASK_STOP_MOVING		0"
+	"		TASK_FACE_ENEMY			0"
+	"		TASK_ANNOUNCE_ATTACK	1"	// 1 = primary attack
+	"		TASK_MELEE_ATTACK1		0"
+	""
+	"	Interrupts"
+	"		COND_ENEMY_DEAD"
+	"		COND_ENEMY_OCCLUDED"
+);
+
+//=========================================================
+// 	SCHED_HIDE
+//=========================================================
+DEFINE_SCHEDULE
+(
+	SCHED_HIDE,
+
+	"	Tasks"
+	"		TASK_SET_FAIL_SCHEDULE		SCHEDULE:SCHED_COMBAT_FACE"
+	"		TASK_STOP_MOVING			0"
+	"		TASK_FIND_COVER_FROM_ENEMY	0"
+	"		TASK_RUN_PATH				0"
+	"		TASK_WAIT_FOR_MOVEMENT		0"
+	"		TASK_REMEMBER				MEMORY:INCOVER"
+	"		TASK_FACE_ENEMY				0"
+	""
+	"	Interrupts"
+	"		COND_HEAR_DANGER"
+	"		COND_NEW_ENEMY"
+	"		COND_ENEMY_DEAD"
+);
+AI_END_CUSTOM_NPC()
+
diff --git a/sp/src/game/server/mod/weapon_custom_melee.h b/sp/src/game/server/mod/weapon_custom_melee.h
new file mode 100644
index 00000000..37cfe6ec
--- /dev/null
+++ b/sp/src/game/server/mod/weapon_custom_melee.h
@@ -0,0 +1,35 @@
+//=//=============================================================================//
+//
+// Purpose: Melee weapon for custom NPCs. Its model can be overridden.
+//
+//	Author: 1upD
+//
+//=============================================================================//
+#include "cbase.h"
+#include "basehlcombatweapon_shared.h"
+#include "weapon_crowbar.h"
+
+
+class CWeaponCustomMelee : public CWeaponCrowbar
+{
+	DECLARE_CLASS(CWeaponCustomMelee, CWeaponCrowbar);
+
+	const char *GetWorldModel() const { return m_iszWeaponModelName.ToCStr(); }
+	virtual void Drop(const Vector &vecVelocity);
+public:
+	string_t m_iszWeaponModelName;
+
+	DECLARE_DATADESC();
+};
+
+void CWeaponCustomMelee::Drop(const Vector &vecVelocity)
+{
+	BaseClass::Drop(vecVelocity);
+	AddSpawnFlags(SF_WEAPON_NO_PLAYER_PICKUP);
+}
+
+LINK_ENTITY_TO_CLASS(weapon_custommelee, CWeaponCustomMelee);
+
+BEGIN_DATADESC(CWeaponCustomMelee)
+	DEFINE_FIELD(m_iszWeaponModelName, FIELD_STRING)
+END_DATADESC()
diff --git a/sp/src/game/server/server_episodic.vpc b/sp/src/game/server/server_episodic.vpc
index 81c9297b..2b3c5c6f 100644
--- a/sp/src/game/server/server_episodic.vpc
+++ b/sp/src/game/server/server_episodic.vpc
@@ -50,6 +50,13 @@ $Project "Server (Episodic)"
 
 		$Folder	"HL2 DLL"
 		{
+			$Folder	"Mod"
+			{
+				$File "mod\npc_lost_soul.cpp"
+				$File "mod\npc_shadow_walker.h"
+				$File "mod\npc_shadow_walker.cpp"
+				$File "mod\weapon_custom_melee.h"
+			}
 			$File	"$SRCDIR\game\shared\episodic\achievements_ep1.cpp"
 			$File	"$SRCDIR\game\shared\episodic\achievements_ep2.cpp"
 			$File	"$SRCDIR\game\shared\episodic\achievements_epx.cpp"