+ 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