Jump to content

questscripts.txt fixes


Recommended Posts

The formatting alone was a much-needed change.  I ran PFP's quest.txt through a code beautifier but it had too much trouble with questscripts.txt.

Link to comment

Welp, I'm doing it all by hand. For now, I'm only formatting every function which doesn't begin with "quest.setScript" and leave the rest alone. I'm already halfway through. Given the size, a full format by hand including the "real" questscripts could take about a year I think.

I sorted everything into different files like events.lua, position.lua, teleport.lua etc. to increase overview. The idea is to build a tool which merges these files into a final questscripts.txt. This way you don't need to keep searching long.

Edited by Lindor
Link to comment

The cutscenes questscripts are interesting. They are all nested functions; the outer function always defines an inner function called "feedback", but the feedback function is never called. Other than with object oriented programming languages like python, in lua functions defined without the "local" keyword really aren't local. I think the cutscenes functions are all just there to overwrite a global (hardcoded) feedback function. Which, if being called, plays a movie or some music or whatever.

In a nutshell, the cutscenes questscripts don't actually play the movie, they define which movie is played next or which music is played next.

The actual play happens inside by the "feedback" function, which is never called from inside questscripts.txt.

Link to comment

The "Platte8G" exists twice

EDIT: I'm convinced that the second "Platte8G" was an accidental spelling mistake, it should be named "Platte8H" instead. Doesn't matter which one you rename, they both do the same.

This should fix a broken teleporter somewhere.

Edited by Lindor
Link to comment

would be interesting to know which teleporter this fixes. any ideas?

EDIT: I think it's a teleporter in the blood forest which teleports your hero to sector BB-30

Edited by Lindor
Link to comment

Usually the hardcoded "getQuestState" function is called like this:

getQuestState({id = 3650})

But for the functions "blutsee" and "blutgrotte" it's called like this:

getQuestState(3650)
getQuestState(3649)

I don't know wether it's a bug or not, but I think so. These are questscripts for some blood forest quests I think. Any known bugs for these quests?

Link to comment
2 hours ago, Lindor said:

These are questscripts for some blood forest quests I think. Any known bugs for these quests?

Yes. Androdion always said the main quest for the Blood Forest seemed to flow wrong.

Actually speaking of which I just looked up these quests and I see a mismatch in one of the entries as well:

quest.createQuest(3650, {
   id = 3650,
   name = "S_BI_3a_N_nn-Ice and Blood Mainstory - Gereinigtes Blut - T",

The ID doesn't match.

  • Like! 1
Link to comment
7 hours ago, Flix said:

Yes. Androdion always said the main quest for the Blood Forest seemed to flow wrong.

Actually speaking of which I just looked up these quests and I see a mismatch in one of the entries as well:

quest.createQuest(3650, {
   id = 3650,
   name = "S_BI_3a_N_nn-Ice and Blood Mainstory - Gereinigtes Blut - T",

The ID doesn't match.

? For me it looks like they match?

10 hours ago, Lindor said:

I don't know wether it's a bug or not, but I think so.

I found many more examples where the getQuestState function is called with an int as parameter. Actually it seems like the call with a table as a parameter is the exception and not vice versa. I still don't know if one of those routines is a bug. If the table call is a bug, then a couple of main quest scripts are a little bit broken, like the teleporting scripts at the Octagolamus valley. But ingame they seem to work well, so I think that the function can be called both ways, I'm just not 100% sure.

Link to comment
questID		functions calling "getQuestState" via table		quest name
339		scorpion						"M_DE_1h_B_rr-DEB5b"
667		enterValley, enterDamm					"M_OR_1i_B_nn-ORB6b"
712		oldDragon, oldDragonBack				"M_DR_1k_G_rr-DRG6"
730		oldDragon, oldDragonBack				"M_DR_1k_B_nn-DRB6a"
1287		showWaterfall						"M_HE_1_nn-Startquest All"
1540		showWaterfall						"M_OR_1g_G_nn-ORG5_Shaman-Ritual"
1570		enterDarkVillage					"S_HU_3c_rr-Das Geisterdorf VT"
1559		showWaterfall						"S_HE_1_N_db-Startquest Multiplayer All"
1622		scorpion						"M_DE_1k_G_nn-DEG5"
3327		golemOben, golemUnten					"S_HU_1_N_nn-Golem_Portal_DONOTDELETE"
3347		oldDragon, oldDragonBack, scorpion			"S_DR_1_N_nn-Dragon Teleport - Free Play - DO NOT DELETE"
3714		Lichinsel						"S_BI_3a_nn-Der verschollene General"
3782		Eisdungeon						"S_BI_5_N_JT - Auf der Spur V"

These are all the quests with table calls. For every ther call of the "getQuestState" function, the id is used directly as a parameter.

Except showWaterfall, all functions are hero teleporting functions.
Are there any bells ringing? Known bugs for these quests? Maybe similarities?

Link to comment

Additional findings:

  • the function "CM_FlushProtocol" doesn't seem to existin spite of being called by "CM_GarbageCollect"; either it's hardcoded or it's an unfinished idea
  • the function "CM_ResolveQuestStates" doesn't do anything, looks like an unfinished idea
  • the function "CM_Timed_OnPrecondsFulfilled" doesn't do anything, looks like an unfinished idea
  • the function "CM_Timed_OnSetup" doesn't do anything, looks like an unfinished idea
  • the function "CM_Timed_OnDeath" doesn't do anything, looks like an unfinished idea
  • the function "CM_Timed_OnWon" doesn't do anything, looks like an unfinished idea
  • the function "CM_Timed_OnLost" doesn't do anything, looks like an unfinished idea

The CM patch scripts look like the very unfinished attempt to transform the questscripts.txt in a more overviewable state by scripting general functions for patterns within questsstages and then just calling the same functions over and over again. But as I said, it looks very unfinished. Next up I'll work on an overview of all hardcoded and non-hardcoded functions and variables.

Edited by Lindor
Link to comment

There's a major mistake in the "_AREA_CENTER_GHOSTVILLAGE" function. The way the "AreaCreatures" table was set up, the entries would overwrite each other and in the end there's basically just one areacreature left. Here's the correction:

function _AREA_CENTER_GHOSTVILLAGE(wpos)
    local AreaCreatures = {
        {
            Tag = 2,
            CID = 1077,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 1076,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 3,
            CID = 1080,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 1078,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 1079,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 1081,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }
    }
    local points, numPoints = getSpawnPoints({position = wpos, radius = 300})
    local creatures = getn(AreaCreatures)
    if points then
        for id, object in ipairs(points) do
            local randomnumber = math.floor(math.random(1, creatures))
            do spawnCreature({
                behaviour = AreaCreatures[randomnumber].Behaviour,
                creature_id = AreaCreatures[randomnumber].CID,
                faction_id = AreaCreatures[randomnumber].Faction,
                equipset_id = AreaCreatures[randomnumber].Equipment,
                mortality = 0,
                position = object
            }) end
        end
    end
end

 

Link to comment
18 hours ago, Lindor said:

The function "onInitWorldobjects" uses "FTYPE_MAGICLIGHT" multiple times while it should be "FXTYPE_MAGICLIGHT". Spelling mistake.

 

As can be seen here, the spelling mistake also exists in the dll files. I don't kow wether to use FTYPE or FXTYPE. Maybe none of those work due to the spelling mistake and other FX need to be applied instead or maybe both work and it doesn't matter. Needs to be tested (@Flix @idbeholdME @dimitrius154 someone wants to test? I can't dew it, my PC would potentially give false negatives due to it requiring minimum settings with PhysX disabled)

Link to comment

There's a big bug in the "_AREA_CENTER_HUMANS_CAPITAL" function. Originally it would spawn two creatures per spawn point. Here's the fix:

function _AREA_CENTER_HUMANS_CAPITAL(wpos)
    local AreaCreatures = {
        {
            Tag = 1,
            CID = 316,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 12,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 325,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 12,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 318,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 12,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1072,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 12,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 327,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 12,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 994,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 12,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 995,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 12,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1043,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 12,
            Equipment = 34
        }, {
            Tag = 2,
            CID = 321,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 736,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 691,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 692,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 966,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 329,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 963,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 578,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 965,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 323,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 331,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 2,
            CID = 712,
            Behaviour = "JOB_KID",
            Faction = 12,
            Equipment = 43
        }, {
            Tag = 3,
            CID = 574,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 575,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 576,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 320,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 322,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 997,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 998,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 999,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 1000,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 1001,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 330,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 324,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 983,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 984,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 985,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 978,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 332,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 979,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 980,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 12,
            Equipment = 33
        }
    }
    local points, numPoints = getSpawnPoints({position = wpos, radius = 500})
    local creatures = getn(AreaCreatures)
    if points then
        for id, object in ipairs(points) do
            local randomnumber = math.floor(math.random(1, creatures))
            do spawnCreature({
                behaviour = AreaCreatures[randomnumber].Behaviour,
                creature_id = AreaCreatures[randomnumber].CID,
                faction_id = AreaCreatures[randomnumber].Faction,
                equipset_id = AreaCreatures[randomnumber].Equipment,
                mortality = 0,
                position = object
            }) end
        end
    end
end

 

Link to comment
9 minutes ago, Lindor said:

There's a big bug in the "_AREA_CENTER_HUMANS_CAPITAL" function. Originally it would spawn two creatures per spawn point. Here's the fix:

The same issue exists for "_AREA_CENTER_LIZARD_2". Fix:

function _AREA_CENTER_LIZARD_2(wpos)
    local AreaCreatures = {
        {
            Tag = 1,
            CID = 1047,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1473,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1474,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1475,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1476,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1477,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1827,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1828,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1829,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1830,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1831,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 1,
            CID = 1832,
            Behaviour = "JOB_RICH_STATIST",
            Faction = 32,
            Equipment = 34
        }, {
            Tag = 3,
            CID = 1105,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 32,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 1161,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 32,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 1162,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 32,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 1106,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 32,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 1163,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 32,
            Equipment = 33
        }, {
            Tag = 3,
            CID = 1164,
            Behaviour = "JOB_POOR_STATIST",
            Faction = 32,
            Equipment = 33
        }
    }
    local points, numPoints = getSpawnPoints({position = wpos, radius = 400})
    local creatures = getn(AreaCreatures)
    if points then
        for id, object in ipairs(points) do
            local randomnumber = math.floor(math.random(1, creatures))
            do spawnCreature({
                behaviour = AreaCreatures[randomnumber].Behaviour,
                creature_id = AreaCreatures[randomnumber].CID,
                faction_id = AreaCreatures[randomnumber].Faction,
                equipset_id = AreaCreatures[randomnumber].Equipment,
                mortality = 0,
                position = object
            }) end
        end
    end
end

 

Link to comment
On 5/20/2023 at 6:05 PM, Flix said:

The formatting alone was a much-needed change.  I ran PFP's quest.txt through a code beautifier but it had too much trouble with questscripts.txt.

I have written my own lua code beautifier now and so far the results are promising. Can probably upload a fully formatted questscripts.txt in 2 weeks. Important functions formatting done by hand, actual questscripts formatting done by machine:smile:

  • Like! 1
Link to comment
  • 2 weeks later...

@dimitrius154 @Flix

These are the cutscene functions being present in EE 3.2A:

function cutscene_DM(args)
function cutscene_DR_bad(args)
function cutscene_DR_good(args)
function cutscene_HE_bad(args)
function cutscene_IN_bad(args)
function cutscene_SE_good(args)
function cutscene_SW(args)
function cutscene_TG_bad(args)
function cutscene_TG_good(args)

It seems like there are three missing, one for DM, HE and SW each. It also seems like you added one of the missing functions in Addendum / Dark mod:

function cutscene_HE_good(args)

Do you two have more insights on them? Why are the missing functions not present? What are the consequences of adding cutscene_HE_good? Why are good and bad mixed into one function for DM / SW?

Link to comment
2 hours ago, Lindor said:

Do you two have more insights on them? Why are the missing functions not present? What are the consequences of adding cutscene_HE_good? Why are good and bad mixed into one function for DM / SW?

cutscene_HE_good is definitely present in vanilla, I've never tampered with it. These look like character starting cinematics, the devs must have considered alignment-dependent variations, but never made it happen, so there's no difference, whether _goog, or _bad is used. The SW introduction must have been coded last, so they didn't bother to make separate version.

  • Thanks! 1
Link to comment
7 minutes ago, dimitrius154 said:

cutscene_HE_good is definitely present in vanilla, I've never tampered with it. These look like character starting cinematics, the devs must have considered alignment-dependent variations, so there's no difference, whether _goog, or _bad is used. The SW introduction must have been coded last, so they didn't bother to make separate version.

It was human error on my end, it's also present in EE 3.2A. Thx for clarification:smile:

  • Like! 1
Link to comment

There is another questscripts.txt fix:
One superfluous comma is breaking the syntax. Correction:

do quest.setScript(2122, "OnDeath", function(args)
    local lizards = {
        {tcid = 6411, alive = true, behaviour = "Enemy_hunter"},
        {tcid = 6413, alive = true, behaviour = "Enemy_warrior_kicknrush"},
        {tcid = 6414, alive = true, behaviour = "Enemy_mage_phalanx"},
        {tcid = 6415, alive = true, behaviour = "Enemy_mage_phalanx"},
        {tcid = 6417, alive = true, behaviour = "Enemy_warrior_brave_ex"},
        {tcid = 6418, alive = true, behaviour = "Enemy_warrior_brave_ex"},
        {tcid = 6419, alive = true, behaviour = "Enemy_warrior_brave_ex"}
    }
    for I, lizard in ipair(lizards) do
        if args.tcid == lizard.tcid then
            do lizard.alive = false end
            do changeCreature({tcid = lizard.tcid, behaviour = "JOB_QUESTSTAGING", emotion = "ANIM_TYPE_SM20", mortality = "IMMORTAL", loopCount = - 1}) end
        end
    end
    if args.tcid == 6360 then
        for I, lizard in ipairs(lizards) do
            if lizard.alive == false then
                do changeCreature({tcid = lizard.tcid, behaviour = "JOB_QUESTSTAGING", emotion = "ANIM_TYPE_IDLE", loopCount = 1}) end
                do changeCreature({tcid = lizard.tcid, behaviour = lizard.behaviour, delay = 3}) end
            end
        end
    end
end) end

Previously, it would say "do lizard.alive = false,". The comma was breaking the syntax.

I don't know wether this syntax bug was present prior to my prettification or not, but it would surprise me if it wasn't.

EDIT: Actually the same issue exists for quest 2123

Edited by Lindor
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...
Please Sign In or Sign Up