class VhtQuest abstract play { int m_mapNum, m_step; 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); } static Line vhtGetLine(int lineId) { return level.lines[level.createLineIdIterator(lineId).next()]; } static bool vhtCheckLever(int lineId) { let ln = vhtGetLine(lineId); if(ln) { let sd = ln.sidedef[Line.FRONT]; if(sd && TexMan.getName(sd.getTexture(Side.MID)) ~== "SW_OL5") { return true; } } return false; } } 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 override void vhtInitHub() { m_fStep0 = new("VhtFnPlayerInSector") .vhtInit(115); m_fStep1 = new("VhtFnPlayerInvAmount").vhtInit("KeySilver", 1); } // 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;} // fall through case 2: // quest 1 step 2: ring the bell let ln = vhtGetLine(2); if(ln && !(ln.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; // quest 3 puzzle item: flame mask VhtFnBoolFuse m_fFlameMask; override void vhtInitHub() { m_fFlameMask = new("VhtFnBoolFuse").vhtInit(new("VhtFnPlayerInvAmount").vhtInit("PuzzFlameMask", 1)); } override void vhtTick() { m_fFlameMask.vhtRun(); } override void vhtTravelled() { // quest 2 step 0: return from guardian of ice if(m_step == 0 && level.levelNum == m_mapNum) { m_step = 1; } } 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 = 1; } } } // quest 4: guardian of fire class VhtQuest4 : VhtQuest { override VhtQuest vhtInit(VhtHubQuest hubQuest) { super.vhtInit(hubQuest); return self; } override void vhtTick() { if(level.levelNum == m_mapNum) { switch(m_step) { case 0: // quest 4 step 0: press the switch if(vhtCheckLever(2)) { m_step = 1; ++VhtQuest2(m_hubQuest).m_guardianOfFire; } break; } } } override string vhtDescribe() { let s = super.vhtDescribe(); if(!VhtQuest2(m_hubQuest).m_fFlameMask.m_result) { s = s .. StringTable.localize("$VHT_QST_4_FireMask"); } return s; } } // 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 m_quests; void vhtAddQuest(class 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) { if(m_quests[i]) { m_quests[i].vhtPreTravelled(); } } } override void travelled() { for(int i = 0, j = m_quests.size(); i < j; ++i) { if(m_quests[i]) { m_quests[i].vhtTravelled(); } } } void vhtTick() { for(int i = 0, j = m_quests.size(); i < j; ++i) { if(m_quests[i]) { m_quests[i].vhtTick(); } } } string vhtDescribe() { string s = ""; for(int i = 0, j = m_quests.size(); i < j; ++i) { if(m_quests[i]) { s.appendFormat( "\cu- \cn%s\c-\n%s\n\n", StringTable.localize( m_quests[i].vhtLevelInfo().levelName, false ), m_quests[i].vhtDescribe() ); } } return s; } }