+ add aesthetic fixes for small hud font to make it consistent with the big hud font
+ add option to add a projectile to timon's axe (splits mana use) + add option to speed up sapphire wand + make pickup flashes bright + make sapphire wand's trail look more like the explosion + add option to display a detailed quest log on the automap + make ettins and centaurs not play a hit sound when missing + add an option to set the behaviour of centaurs to make them more vulnerable + add an option to make players shatter frozen enemies on touch + add an option to change the sapphire wand's damage function + make sapphire wand's projectile appear at the proper height + add an option to change the frost spell's damage function + add an option to make bloodscourge's projectiles foil invulnerability
This commit is contained in:
		
						commit
						6928c2f898
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | gzdoom-crash.log | ||||||
							
								
								
									
										8
									
								
								cvarinfo.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								cvarinfo.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | server bool vht_faxe_projectile         = true; | ||||||
|  | server int  vht_mwand_damagefunc        = 0; | ||||||
|  | server int  vht_mwand_speed             = 1; | ||||||
|  | server int  vht_mfrost_damagefunc       = 1; | ||||||
|  | server bool vht_mbloodscourge_foilinvul = false; | ||||||
|  | server bool vht_player_touchshatter     = true; | ||||||
|  | server bool vht_player_questlog         = true; | ||||||
|  | server int  vht_monster_centaur         = 2; | ||||||
							
								
								
									
										
											BIN
										
									
								
								graphics/SMALLIN1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								graphics/SMALLIN1.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 876 B | 
							
								
								
									
										
											BIN
										
									
								
								graphics/SMALLIN4.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								graphics/SMALLIN4.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 883 B | 
							
								
								
									
										
											BIN
										
									
								
								graphics/SMALLIN7.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								graphics/SMALLIN7.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 882 B | 
							
								
								
									
										61
									
								
								language.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								language.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | ||||||
|  | [en default] | ||||||
|  | OPTMNU_VHT = "Vanilla Hexen Tweaks"; | ||||||
|  | 
 | ||||||
|  | OB_VHTFWEAPAXE = "%o rode the axe-lightning from %k."; | ||||||
|  | 
 | ||||||
|  | VHT_FAXE_PROJECTILE         = "Timon's Axe Also Fires a Projectile"; | ||||||
|  | VHT_MWAND_DAMAGEFUNC        = "Wand Damage Function"; | ||||||
|  | VHT_MWAND_SPEED             = "Wand Speed Increase"; | ||||||
|  | VHT_MFROST_DAMAGEFUNC       = "Frost Shards Damage Function"; | ||||||
|  | VHT_MBLOODSCOURGE_FOILINVUL = "Bloodscourge Foils Invulnerability"; | ||||||
|  | VHT_PLAYER_TOUCHSHATTER     = "Shatter Frozen Enemies On Touch"; | ||||||
|  | VHT_PLAYER_QUESTLOG         = "Enable Quest Log"; | ||||||
|  | VHT_MONSTER_CENTAUR         = "Centaur Behaviour"; | ||||||
|  | 
 | ||||||
|  | VHT_OPT_CONSTANT  = "Constant"; | ||||||
|  | VHT_OPT_MODIFIED  = "Modified"; | ||||||
|  | VHT_OPT_VANILLA   = "Vanilla"; | ||||||
|  | VHT_OPT_NOREFLECT = "No Projectile Reflection"; | ||||||
|  | VHT_OPT_ANGLED    = "No Reflection, Back is Vulnerable"; | ||||||
|  | 
 | ||||||
|  | VHT_QST_1_0 = | ||||||
|  | 	"@ must find the emerald key\n" | ||||||
|  | 	"and get through the stronghold.\n" | ||||||
|  | 	"@' note says, 'it lays beyond\n" | ||||||
|  | 	"a stained warrior.'"; | ||||||
|  | VHT_QST_1_1 = | ||||||
|  | 	"the chapel stands tall and\n" | ||||||
|  | 	"proud in the name of sin,\n" | ||||||
|  | 	"but its doors stay locked.\n" | ||||||
|  | 	"@ must find the silver key."; | ||||||
|  | VHT_QST_1_2 = | ||||||
|  | 	"@ need to ring the chapel's bell,\n" | ||||||
|  | 	"to call for the doom about\n" | ||||||
|  | 	"to befall cronos, and to build\n" | ||||||
|  | 	"a path forward."; | ||||||
|  | VHT_QST_1_3 = | ||||||
|  | 	"now, @ must find @' way to\n" | ||||||
|  | 	"the first step -- the seven portals.\n" | ||||||
|  | 	"\cr@ will not be able to return."; | ||||||
|  | 
 | ||||||
|  | VHT_QST_2_0 = | ||||||
|  | 	"the first step on @' journey\n" | ||||||
|  | 	"shall be to get through the guardians\n" | ||||||
|  | 	"which seal the realm beyond.\n" | ||||||
|  | 	"\n" | ||||||
|  | 	"the portals once meant to defend cronos\n" | ||||||
|  | 	"from invasion now merely keep @= from\n" | ||||||
|  | 	"delivering justice unto it."; | ||||||
|  | VHT_QST_2_1 = | ||||||
|  | 	"with the guardian of ice opened,\n" | ||||||
|  | 	"two more paths become available to @=:\n" | ||||||
|  | 	"- guardian of fire: %i/1\n" | ||||||
|  | 	"- guardian of steel: %i/2"; | ||||||
|  | 
 | ||||||
|  | VHT_QST_3_0 = | ||||||
|  | 	"all that seems to be left here is\n" | ||||||
|  | 	"a switch, and some portals... perhaps\n" | ||||||
|  | 	"all @ need is to pass through here for now."; | ||||||
|  | VHT_QST_3_1 = | ||||||
|  | 	"there doesn't seem to be anything here\n" | ||||||
|  | 	"for @= right now."; | ||||||
							
								
								
									
										4
									
								
								mapinfo.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								mapinfo.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | ||||||
|  | GameInfo { | ||||||
|  | 	PlayerClasses = "VhtFighterPlayer", "VhtClericPlayer", "VhtMagePlayer" | ||||||
|  | 	AddEventHandlers = "VhtEvents" | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								menudef.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								menudef.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | OptionValue "VhtDamageFunc" { | ||||||
|  | 	0, "$VHT_OPT_VANILLA" | ||||||
|  | 	1, "$VHT_OPT_MODIFIED" | ||||||
|  | 	2, "$VHT_OPT_CONSTANT" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | OptionValue "VhtOnOff" { | ||||||
|  | 	0, "$VHT_OPT_VANILLA" | ||||||
|  | 	1, "$VHT_OPT_MODIFIED" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | OptionValue "VhtCentaurBehaviour" { | ||||||
|  | 	0, "$VHT_OPT_VANILLA" | ||||||
|  | 	1, "$VHT_OPT_NOREFLECT" | ||||||
|  | 	2, "$VHT_OPT_ANGLED" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | AddOptionMenu "OptionsMenu" { | ||||||
|  | 	SubMenu "$OPTMNU_VHT", "VhtMenu" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | OptionMenu "VhtMenu" { | ||||||
|  | 	Title "$OPTMNU_VHT" | ||||||
|  | 	StaticText "Weapons" | ||||||
|  | 	Option "$VHT_FAXE_PROJECTILE", "vht_faxe_projectile", "OnOff" | ||||||
|  | 	Option "$VHT_MWAND_DAMAGEFUNC", "vht_mwand_damagefunc", "VhtDamageFunc" | ||||||
|  | 	ScaleSlider "$VHT_MWAND_SPEED", "vht_mwand_speed", 0, 6, 1, "$VHT_OPT_VANILLA" | ||||||
|  | 	Option "$VHT_MFROST_DAMAGEFUNC", "vht_mfrost_damagefunc", "VhtDamageFunc" | ||||||
|  | 	Option "$VHT_MBLOODSCOURGE_FOILINVUL", "vht_mbloodscourge_foilinvul", "OnOff" | ||||||
|  | 	StaticText "Players" | ||||||
|  | 	Option "$VHT_PLAYER_TOUCHSHATTER", "vht_player_touchshatter", "OnOff" | ||||||
|  | 	Option "$VHT_PLAYER_QUESTLOG", "vht_player_questlog", "OnOff" | ||||||
|  | 	StaticText "Monsters" | ||||||
|  | 	Option "$VHT_MONSTER_CENTAUR", "vht_monster_centaur", "VhtCentaurBehaviour" | ||||||
|  | } | ||||||
							
								
								
									
										69
									
								
								vhtzs/events.zsc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								vhtzs/events.zsc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,69 @@ | ||||||
|  | class VhtEvents : StaticEventHandler { | ||||||
|  | 	bool           m_useQuestLog; | ||||||
|  | 	string         m_questLog; | ||||||
|  | 	VhtFnPlayerInv m_fGetQuests; | ||||||
|  | 	VhtQuestHolder vhtGetQuests() const { | ||||||
|  | 		return m_fGetQuests.vhtRun() ? VhtQuestHolder(m_fGetQuests.m_result) : null; | ||||||
|  | 	} | ||||||
|  | 	override void playerEntered(PlayerEvent e) { | ||||||
|  | 		let p = players[e.playerNumber].mo; | ||||||
|  | 		if(p && !p.findInventory("VhtQuestHolder")) { | ||||||
|  | 			p.giveInventoryType("VhtQuestHolder"); | ||||||
|  | 		} | ||||||
|  | 		if(!m_fGetQuests) { | ||||||
|  | 			m_fGetQuests = new("VhtFnPlayerInvExist").vhtInit("VhtQuestHolder"); | ||||||
|  | 		} | ||||||
|  | 		let qh = vhtGetQuests(); | ||||||
|  | 		if(!e.isReturn && m_fGetQuests.m_player == e.playerNumber) { | ||||||
|  | 			qh.vhtAddQuest("VhtQuest" .. level.levelNum); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	override void playerDisconnected(PlayerEvent e) { | ||||||
|  | 		let p = players[e.playerNumber].mo; | ||||||
|  | 		if(p) { | ||||||
|  | 			let qh_r = VhtQuestHolder(p.findInventory("VhtQuestHolder")); | ||||||
|  | 			if(qh_r) { | ||||||
|  | 				p.removeInventory(qh_r); | ||||||
|  | 				let qh_l = vhtGetQuests(); | ||||||
|  | 				if(qh_l) { | ||||||
|  | 					qh_r.m_quests.move(qh_l.m_quests); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	override void worldTick() { | ||||||
|  | 		m_useQuestLog = vht_player_questlog; | ||||||
|  | 		let qh = vhtGetQuests(); | ||||||
|  | 		if(!qh) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		for(int i = 0, j = qh.m_quests.size(); i < j; ++i) { | ||||||
|  | 			if(qh.m_quests[i]) { | ||||||
|  | 				qh.m_quests[i].vhtTick(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if(m_useQuestLog) { | ||||||
|  | 			m_questLog = ""; | ||||||
|  | 			for(int i = 0, j = qh.m_quests.size(); i < j; ++i) { | ||||||
|  | 				if(qh.m_quests[i]) { | ||||||
|  | 					m_questLog.appendFormat( | ||||||
|  | 						"\cu- \cn%s\c-\n%s\n\n", | ||||||
|  | 						StringTable.localize( | ||||||
|  | 							qh.m_quests[i].vhtLevelInfo().levelName, | ||||||
|  | 							false | ||||||
|  | 						), | ||||||
|  | 						qh.m_quests[i].vhtDescribe() | ||||||
|  | 					); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	override void renderUnderlay(RenderEvent e) { | ||||||
|  | 		if(automapActive && m_useQuestLog) { | ||||||
|  | 			double x = Screen.getWidth()  / 320.0; | ||||||
|  | 			double y = Screen.getHeight() / 8.0; | ||||||
|  | 			Screen.drawText(smallfont, Font.CR_UNTRANSLATED, x+x, y+x, m_questLog, DTA_CLEANNOMOVE_1,true, DTA_ALPHA,0.406, DTA_FILLCOLOR,0); | ||||||
|  | 			Screen.drawText(smallfont, Font.CR_UNTRANSLATED, x, y, m_questLog, DTA_CLEANNOMOVE_1,true); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										56
									
								
								vhtzs/fnplayer.zsc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								vhtzs/fnplayer.zsc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | ||||||
|  | class VhtFnPlayer abstract { | ||||||
|  | 	int m_player; | ||||||
|  | 	virtual bool vhtCall(PlayerInfo p) {return false;} | ||||||
|  | 	bool vhtRun() { | ||||||
|  | 		for(int i = 0; i < MAXPLAYERS; ++i) { | ||||||
|  | 			if(playerInGame[i] && vhtCall(players[i])) { | ||||||
|  | 				m_player = i; | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtFnPlayerInSector : VhtFnPlayer { | ||||||
|  | 	int m_idx; | ||||||
|  | 	VhtFnPlayer vhtInit(int idx) { | ||||||
|  | 		m_idx = idx; | ||||||
|  | 		return self; | ||||||
|  | 	} | ||||||
|  | 	override bool vhtCall(PlayerInfo p) { | ||||||
|  | 		return p.mo.curSector.index() == m_idx; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtFnPlayerInv : VhtFnPlayer abstract { | ||||||
|  | 	class<Inventory> m_which; | ||||||
|  | 	Inventory        m_result; | ||||||
|  | 	override bool vhtCall(PlayerInfo p) { | ||||||
|  | 		let inv = p.mo.findInventory(m_which); | ||||||
|  | 		if(inv) { | ||||||
|  | 			m_result = inv; | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtFnPlayerInvExist : VhtFnPlayerInv { | ||||||
|  | 	VhtFnPlayerInv vhtInit(class<Inventory> which) { | ||||||
|  | 		m_which = which; | ||||||
|  | 		return self; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtFnPlayerInvAmount : VhtFnPlayerInv { | ||||||
|  | 	int m_amount; | ||||||
|  | 	VhtFnPlayerInv vhtInit(class<Inventory> which, int amount) { | ||||||
|  | 		m_which  = which; | ||||||
|  | 		m_amount = amount; | ||||||
|  | 		return self; | ||||||
|  | 	} | ||||||
|  | 	override bool vhtCall(PlayerInfo p) { | ||||||
|  | 		return super.vhtCall(p) && m_result.amount >= m_amount; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								vhtzs/fx.zsc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vhtzs/fx.zsc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | class VhtPickupFlash : PickupFlash replaces PickupFlash { | ||||||
|  | 	default { | ||||||
|  | 		+Bright; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtMageWandSmoke : MageWandSmoke replaces MageWandSmoke { | ||||||
|  | 	default { | ||||||
|  | 		RenderStyle "Add"; | ||||||
|  | 		Translation "156:163=217:223"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								vhtzs/monsters.zsc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vhtzs/monsters.zsc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | ||||||
|  | class VhtEttin : Ettin replaces Ettin { | ||||||
|  | 	default { | ||||||
|  | 		AttackSound ""; | ||||||
|  | 	} | ||||||
|  | 	states { | ||||||
|  | 	Melee: | ||||||
|  | 		ETTN EF 6 a_faceTarget; | ||||||
|  | 		ETTN G 8 a_customMeleeAttack(random[EttinAttack](1, 8) * 2, "EttinAttack", "FighterPunchMiss"); | ||||||
|  | 		goto See; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtCentaur : Centaur replaces Centaur { | ||||||
|  | 	default { | ||||||
|  | 		AttackSound ""; | ||||||
|  | 	} | ||||||
|  | 	void vhtSetReflectiveInvulnerable() { | ||||||
|  | 		bInvulnerable = true; | ||||||
|  | 		if(vht_monster_centaur != 0) | ||||||
|  | 			bReflective = true; | ||||||
|  | 	} | ||||||
|  | 	void vhtUnsetReflectiveInvulnerable() { | ||||||
|  | 		bInvulnerable = false; | ||||||
|  | 		if(vht_monster_centaur != 0) | ||||||
|  | 			bReflective = false; | ||||||
|  | 	} | ||||||
|  | 	override int damageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags, double hitAngle) { | ||||||
|  | 		if(vht_monster_centaur == 2 && bInvulnerable) { | ||||||
|  | 			double angleToSrc = inflictor ? angleTo(inflictor) - angle : hitAngle; | ||||||
|  | 			if(angleToSrc < -90 || angleToSrc > 90) { | ||||||
|  | 				flags |= DMG_FOILINVUL; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return super.damageMobj(inflictor, source, damage, mod, flags, angle); | ||||||
|  | 	} | ||||||
|  | 	states { | ||||||
|  | 	Pain: | ||||||
|  | 		CENT G 6 a_pain; | ||||||
|  | 		CENT G 6 vhtSetReflectiveInvulnerable; | ||||||
|  | 		CENT EEE 15 a_centaurDefend; | ||||||
|  | 		CENT E 1 vhtUnsetReflectiveInvulnerable; | ||||||
|  | 		goto See; | ||||||
|  | 	Melee: | ||||||
|  | 		CENT H 5 a_faceTarget; | ||||||
|  | 		CENT I 4 a_faceTarget; | ||||||
|  | 		CENT J 7 a_customMeleeAttack(random[CentaurAttack](3, 9), "CentaurAttack", "FighterHammerMiss"); | ||||||
|  | 		goto See; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								vhtzs/player.zsc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								vhtzs/player.zsc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | mixin class VhtPlayer { | ||||||
|  | 	bool m_touchShatter; | ||||||
|  | 	override bool canCollideWith(Actor other, bool passive) { | ||||||
|  | 		if(m_touchShatter && other.bIceCorpse && other.distance3D(other) <= other.radius + 4) { | ||||||
|  | 			other.damageMobj(self, self, 1, 'Melee'); | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	override void tick() { | ||||||
|  | 		m_touchShatter = vht_player_touchshatter; | ||||||
|  | 		super.tick(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtFighterPlayer : FighterPlayer { | ||||||
|  | 	mixin VhtPlayer; | ||||||
|  | 	default { | ||||||
|  | 		Player.WeaponSlot 1, "FWeapFist"; | ||||||
|  | 		Player.WeaponSlot 2, "VhtFWeapAxe"; | ||||||
|  | 		Player.WeaponSlot 3, "FWeapHammer"; | ||||||
|  | 		Player.WeaponSlot 4, "FWeapQuietus"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtClericPlayer : ClericPlayer { | ||||||
|  | 	mixin VhtPlayer; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtMagePlayer : MagePlayer { | ||||||
|  | 	mixin VhtPlayer; | ||||||
|  | 	default { | ||||||
|  | 		Player.StartItem "VhtMWeapWand"; | ||||||
|  | 		Player.WeaponSlot 1, "VhtMWeapWand"; | ||||||
|  | 		Player.WeaponSlot 2, "MWeapFrost"; | ||||||
|  | 		Player.WeaponSlot 3, "MWeapLightning"; | ||||||
|  | 		Player.WeaponSlot 4, "MWeapBloodscourge"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										67
									
								
								vhtzs/projectiles.zsc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								vhtzs/projectiles.zsc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,67 @@ | ||||||
|  | class VhtMageWandMissile : MageWandMissile replaces MageWandMissile { | ||||||
|  | 	default { | ||||||
|  | 		DamageFunction vhtDamageFunc(); | ||||||
|  | 	} | ||||||
|  | 	override void beginPlay() { | ||||||
|  | 		super.beginPlay(); | ||||||
|  | 		spriteOffset = (0, 8); | ||||||
|  | 	} | ||||||
|  | 	int vhtDamageFunc() { | ||||||
|  | 		switch(vht_mwand_damagefunc) { | ||||||
|  | 		case 0: return 2 * random(1, 8); /* vanilla  (2d8) */ | ||||||
|  | 		case 1: return 4 * random(1, 4); /* modified (4d4) */ | ||||||
|  | 		case 2: return 16;               /* constant       */ | ||||||
|  | 		} | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtFrostMissile : FrostMissile replaces FrostMissile { | ||||||
|  | 	default { | ||||||
|  | 		DamageFunction vhtDamageFunc(); | ||||||
|  | 	} | ||||||
|  | 	int vhtDamageFunc() { | ||||||
|  | 		switch(vht_mfrost_damagefunc) { | ||||||
|  | 		case 0: return 1 * random(1, 8); /* vanilla  (1d8) */ | ||||||
|  | 		case 1: return 4 * random(1, 3); /* modified (4d3) */ | ||||||
|  | 		case 2: return 8;                /* constant       */ | ||||||
|  | 		} | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtBloodscourgeShot : MageStaffFx2 replaces MageStaffFx2 { | ||||||
|  | 	override void beginPlay() { | ||||||
|  | 		super.beginPlay(); | ||||||
|  | 		if(vht_mbloodscourge_foilinvul) { | ||||||
|  | 			bFoilInvul = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtAxeMissile : Actor { | ||||||
|  | 	default { | ||||||
|  | 		Speed 25; | ||||||
|  | 		Radius 13; | ||||||
|  | 		Height 8; | ||||||
|  | 		Damage 2; | ||||||
|  | 		DamageType "Melee"; | ||||||
|  | 		Projectile; | ||||||
|  | 		DeathSound "MageLightningZap"; | ||||||
|  | 		Obituary "$OB_VHTFWEAPAXE"; | ||||||
|  | 		Translation "146:163=146:160", "217:223=155:163"; | ||||||
|  | 	} | ||||||
|  | 	states { | ||||||
|  | 	Spawn: | ||||||
|  | 		SHRD A 2 bright; | ||||||
|  | 		SHRD ABC 3 bright; | ||||||
|  | 		loop; | ||||||
|  | 	Death: | ||||||
|  | 		MWND E 4 bright; | ||||||
|  | 		MWND F 3 bright; | ||||||
|  | 		MWND G 4 bright; | ||||||
|  | 		MWND H 3 bright; | ||||||
|  | 		MWND I 4 bright; | ||||||
|  | 		stop; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										155
									
								
								vhtzs/quest.zsc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								vhtzs/quest.zsc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,155 @@ | ||||||
|  | class VhtQuest abstract play { | ||||||
|  | 	int         m_mapNum, m_step, m_flags; | ||||||
|  | 	VhtHubQuest m_hubQuest; | ||||||
|  | 	virtual VhtQuest vhtInit(VhtHubQuest hubQuest) { | ||||||
|  | 		m_mapNum   = level.levelNum; | ||||||
|  | 		m_hubQuest = hubQuest; | ||||||
|  | 		return self; | ||||||
|  | 	} | ||||||
|  | 	virtual void vhtTick() {} | ||||||
|  | 	virtual void vhtTravelled() {} | ||||||
|  | 	virtual void vhtPreTravelled() {} | ||||||
|  | 	virtual string vhtDescribe() { | ||||||
|  | 		let s = StringTable.localize("$VHT_QST_" .. m_mapNum .. "_" .. m_step); | ||||||
|  | 		s.replace("@=", multiplayer ? "us"  : "me"); | ||||||
|  | 		s.replace("@'", multiplayer ? "our" : "my"); | ||||||
|  | 		s.replace("@",  multiplayer ? "we"  : "i"); | ||||||
|  | 		return s; | ||||||
|  | 	} | ||||||
|  | 	LevelInfo vhtLevelInfo() const { | ||||||
|  | 		return LevelInfo.findLevelByNum(m_mapNum); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtHubQuest : VhtQuest abstract { | ||||||
|  | 	override VhtQuest vhtInit(VhtHubQuest hubQuest) { | ||||||
|  | 		super.vhtInit(self); | ||||||
|  | 		vhtInitHub(); | ||||||
|  | 		return self; | ||||||
|  | 	} | ||||||
|  | 	virtual void vhtInitHub() {} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // quest 1: winnowing hall | ||||||
|  | class VhtQuest1 : VhtHubQuest { | ||||||
|  | 	VhtFnPlayer m_fStep0; // quest 1 step 0: walk into courtyard | ||||||
|  | 	VhtFnPlayer m_fStep1; // quest 1 step 1: pick up silver key | ||||||
|  | 	Line        m_lStep2; // quest 1 step 2: ring the bell | ||||||
|  | 	override void vhtInitHub() { | ||||||
|  | 		m_fStep0 = new("VhtFnPlayerInSector") .vhtInit(115); | ||||||
|  | 		m_fStep1 = new("VhtFnPlayerInvAmount").vhtInit("KeySilver", 1); | ||||||
|  | 		m_lStep2 = level.lines[level.createLineIdIterator(2).next()]; | ||||||
|  | 	} | ||||||
|  | 	// same hub, but cannot return | ||||||
|  | 	override void vhtTravelled() { | ||||||
|  | 		destroy(); | ||||||
|  | 	} | ||||||
|  | 	override void vhtTick() { | ||||||
|  | 		switch(m_step) { | ||||||
|  | 		case 0: if(m_fStep0.vhtRun())                    {m_step = 1;} break; | ||||||
|  | 		case 1: if(m_fStep1.vhtRun())                    {m_step = 2;} // --> | ||||||
|  | 		case 2: if(!(m_lStep2.flags & Line.ML_BLOCKING)) {m_step = 3;} break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // quest 2: seven portals | ||||||
|  | class VhtQuest2 : VhtHubQuest { | ||||||
|  | 	// quest 2 step 1: 3 switches pulled in first puzzle | ||||||
|  | 	int m_guardianOfFire, m_guardianOfSteel; | ||||||
|  | 	override void vhtTravelled() { | ||||||
|  | 		// quest 2 step 0: return from guardian of ice | ||||||
|  | 		if(m_step == 0 && level.levelNum == m_mapNum) { | ||||||
|  | 			++m_step; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	override string vhtDescribe() { | ||||||
|  | 		let s = super.vhtDescribe(); | ||||||
|  | 		if(m_step == 1) { | ||||||
|  | 			s = string.format(s, m_guardianOfFire, m_guardianOfSteel); | ||||||
|  | 		} | ||||||
|  | 		return s; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // quest 3: guardian of ice | ||||||
|  | class VhtQuest3 : VhtQuest { | ||||||
|  | 	override void vhtPreTravelled() { | ||||||
|  | 		// quest 3 step 0: exit to hub | ||||||
|  | 		if(m_step == 0) { | ||||||
|  | 			++m_step; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // quest 4: guardian of fire | ||||||
|  | class VhtQuest4 : VhtQuest {} | ||||||
|  | 
 | ||||||
|  | // quest 5: guardian of steel | ||||||
|  | class VhtQuest5 : VhtQuest {} | ||||||
|  | 
 | ||||||
|  | // quest 6: bright crucible | ||||||
|  | class VhtQuest6 : VhtQuest {} | ||||||
|  | 
 | ||||||
|  | class VhtQuest13 : VhtHubQuest {} | ||||||
|  | class VhtQuest8  : VhtQuest {} | ||||||
|  | class VhtQuest9  : VhtQuest {} | ||||||
|  | class VhtQuest10 : VhtQuest {} | ||||||
|  | class VhtQuest12 : VhtQuest {} | ||||||
|  | class VhtQuest11 : VhtQuest {} | ||||||
|  | 
 | ||||||
|  | class VhtQuest27 : VhtHubQuest {} | ||||||
|  | class VhtQuest32 : VhtQuest {} | ||||||
|  | class VhtQuest33 : VhtQuest {} | ||||||
|  | class VhtQuest34 : VhtQuest {} | ||||||
|  | class VhtQuest28 : VhtQuest {} | ||||||
|  | class VhtQuest30 : VhtQuest {} | ||||||
|  | class VhtQuest31 : VhtQuest {} | ||||||
|  | 
 | ||||||
|  | class VhtQuest22 : VhtHubQuest {} | ||||||
|  | class VhtQuest21 : VhtQuest {} | ||||||
|  | class VhtQuest23 : VhtQuest {} | ||||||
|  | class VhtQuest24 : VhtQuest {} | ||||||
|  | class VhtQuest25 : VhtQuest {} | ||||||
|  | class VhtQuest26 : VhtQuest {} | ||||||
|  | 
 | ||||||
|  | class VhtQuest35 : VhtHubQuest {} | ||||||
|  | class VhtQuest36 : VhtQuest {} | ||||||
|  | class VhtQuest37 : VhtQuest {} | ||||||
|  | class VhtQuest38 : VhtQuest {} | ||||||
|  | class VhtQuest39 : VhtQuest {} | ||||||
|  | 
 | ||||||
|  | class VhtQuest40 : VhtHubQuest {} | ||||||
|  | 
 | ||||||
|  | class VhtQuestHolder : Inventory { | ||||||
|  | 	default { | ||||||
|  | 		Inventory.InterHubAmount 0; | ||||||
|  | 		+Inventory.UnDroppable; | ||||||
|  | 		+Inventory.UnClearable; | ||||||
|  | 	} | ||||||
|  | 	VhtHubQuest     m_hubQuest; | ||||||
|  | 	array<VhtQuest> m_quests; | ||||||
|  | 	void vhtAddQuest(class<VhtQuest> ty) { | ||||||
|  | 		if(ty) { | ||||||
|  | 			let qst = VhtQuest(new(ty)).vhtInit(m_hubQuest); | ||||||
|  | 			if(qst is "VhtHubQuest") { | ||||||
|  | 				m_hubQuest = VhtHubQuest(qst); | ||||||
|  | 			} | ||||||
|  | 			m_quests.push(qst); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	override void depleteOrDestroy() { | ||||||
|  | 		m_hubQuest = null; | ||||||
|  | 		m_quests.clear(); | ||||||
|  | 	} | ||||||
|  | 	override void preTravelled() { | ||||||
|  | 		for(int i = 0, j = m_quests.size(); i < j; ++i) { | ||||||
|  | 			m_quests[i].vhtPreTravelled(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	override void travelled() { | ||||||
|  | 		for(int i = 0, j = m_quests.size(); i < j; ++i) { | ||||||
|  | 			m_quests[i].vhtTravelled(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								vhtzs/weapons.zsc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vhtzs/weapons.zsc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | ||||||
|  | class VhtFWeapAxe : FWeapAxe replaces FWeapAxe { | ||||||
|  | 	override void beginPlay() { | ||||||
|  | 		super.beginPlay(); | ||||||
|  | 		if(vht_faxe_projectile) { | ||||||
|  | 			ammoUse1 = 1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	action void vhtFAxeAttack() { | ||||||
|  | 		if(!player) return; | ||||||
|  | 		if(vht_faxe_projectile) { | ||||||
|  | 			let wep = player.readyWeapon; | ||||||
|  | 			if(wep.ammo1 && wep.ammo1.amount > 0) { | ||||||
|  | 				a_fireProjectile("VhtAxeMissile"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		a_fAxeAttack(); | ||||||
|  | 	} | ||||||
|  | 	states { | ||||||
|  | 	FireGlow: | ||||||
|  | 		FAXE N 4 offset(15, 32); | ||||||
|  | 		FAXE O 3 offset(15, 32); | ||||||
|  | 		FAXE P 2 offset(15, 32); | ||||||
|  | 		FAXE P 1 offset(-5, 70) vhtFAxeAttack; | ||||||
|  | 		FAXE P 2 offset(-25, 90); | ||||||
|  | 		FAXE Q 1 offset(15, 32); | ||||||
|  | 		FAXE Q 2 offset(10, 54); | ||||||
|  | 		FAXE Q 7 offset(10, 150); | ||||||
|  | 		FAXE A 1 offset(0, 60) a_reFire; | ||||||
|  | 		FAXE A 1 offset(0, 52); | ||||||
|  | 		FAXE A 1 offset(0, 44); | ||||||
|  | 		FAXE A 1 offset(0, 36); | ||||||
|  | 		FAXE A 1; | ||||||
|  | 		goto ReadyGlow; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class VhtMWeapWand : MWeapWand replaces MWeapWand { | ||||||
|  | 	states { | ||||||
|  | 	Fire: | ||||||
|  | 		MWND A 0 a_setTics(6 - clamp(vht_mwand_speed, 0, 6)); | ||||||
|  | 		MWND B 0 bright offset(0, 48) { | ||||||
|  | 			a_setTics(6 - clamp(vht_mwand_speed, 0, 6)); | ||||||
|  | 			a_fireProjectile("MageWandMissile"); | ||||||
|  | 		} | ||||||
|  | 		MWND A 3 offset(0, 40); | ||||||
|  | 		MWND A 3 offset(0, 36) a_reFire; | ||||||
|  | 		goto Ready; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								zscript.zsc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								zscript.zsc
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | version "4.8" | ||||||
|  | 
 | ||||||
|  | #include "vhtzs/fnplayer.zsc" | ||||||
|  | #include "vhtzs/fx.zsc" | ||||||
|  | #include "vhtzs/projectiles.zsc" | ||||||
|  | #include "vhtzs/weapons.zsc" | ||||||
|  | #include "vhtzs/player.zsc" | ||||||
|  | #include "vhtzs/monsters.zsc" | ||||||
|  | #include "vhtzs/quest.zsc" | ||||||
|  | #include "vhtzs/events.zsc" | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user