+ 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