lothavor's legacy

General discussion regarding the OpenMW project.
For technical support, please use the Support subforum.
Post Reply
User avatar
sirherrbatka
Posts: 2121
Joined: 07 Aug 2011, 17:21

lothavor's legacy

Post by sirherrbatka » 09 Oct 2017, 06:29

I manged to beat lothavor's legacy quest mod, and oh boy what a bugfest that was. I write this post to describe how did i hacked my way trough.

1) getposition scripts are weird.
Not sure what is up with this, but this mod runs largeish script that does stuff depending on how far you are from point located in exterior cell. getPosition seems to have issues when measuring distance between exterior cells, so you may be under impression that this script does nothing and you are free to go away. Don't do it. getPosition will measure proper distance after enter interior/save/load/enter exterior cycle. This can be also used to stop those pesky earthquakes at the end.

Code: Select all

Begin li_main

; This is the One Script, the master script that controls everything  ; )
; No, seriously - this script provides crucial information used by many other scripts and dialog entries.
; If it gets terminated, lots of things will break!

float distance
float distance2
float timer1sec
short wasInMenu
float lastGameHour
short sleepWait
short sleepWaitPrev
short inEffectsZone
short teleportSpell
short teleportMsg
short randomTeleport
short bountySave
short playerBerserk
float exhaustTime
short saveDisableDone
float temp


; create a continuous hour timescale for general use
set li_g_hours to GameHour
set li_g_hours to li_g_hours + ( DaysPassed * 24 )

; check if player is waiting or sleeping (fast-forward time mode)
set li_g_PCSleepWait to 0
set sleepWaitPrev to sleepWait
set sleepWait to 0
if ( MenuMode == 1 )
	if ( wasInMenu == 1 )
		if ( lastGameHour != GameHour )	; time changed while in menu - must be sleep or wait state
			set sleepWait to 1
			set li_g_PCSleepWait to 1
		endif
	endif
	if ( sleepWaitPrev == 1 )		; since time only advances every other frame
		set li_g_PCSleepWait to 1
	endif
	set lastGameHour to GameHour
endif
set wasInMenu to MenuMode

; used in disposition change calculations
set li_g_DispBonus to ( li_DispoCalibrator -> GetDisposition ) - 50

; used in level-adjusted damage calculations
set temp to ( player -> GetHealth )
if ( temp > 0 )
	set li_g_playerMaxHealth to  temp / ( player -> GetHealthGetRatio )
endif

; delay for Fiend Mode Greetings
if ( li_g_fm_FGTimer > 0 )
	if ( MenuMode == 0 )
		set li_g_fm_FGTimer to li_g_fm_FGTimer - GetSecondsPassed
	endif
endif

; calculate player distance from the island's center
if ( GetInterior == 1 )
	if ( GetPCCell "Heralds' Haven" == 1 )
		set distance to 0
		set distance2 to 0
	elseif ( GetPCCell "Fort Forcewell" == 1 )
		set distance to 3500
		set distance2 to 3500
	elseif ( GetPCCell "Aurora Isle" == 1 )
		set distance to 5000
		set distance2 to 5000
	else
		set distance to 150000
		set distance2 to 150000
	endif
else
	set distance to player -> GetDistance, "li_island_center_marker"
	set distance2 to player -> GetDistance, "li_island_center_marker2"
endif

if ( distance < distance2 )
	set li_g_islandDistance to distance
else
	set li_g_islandDistance to distance2
endif

; delayed call of random teleport script, so it won't crash the game
; (one of those unresolved mysteries with TESScript...)
if ( randomTeleport == 1 )
	StartScript li_randomTeleport
	set randomTeleport to 0
endif

; set the "special rules" if close to the island
if ( inEffectsZone == 0 )
	if ( li_g_islandDistance < 25000 )		; player enters the island zone
		if ( li_g_islandRuin < 9 )
			DisableTeleporting
		endif
		if ( li_g_islandRuin < 4 )
			if ( GetJournalIndex "LI_J_NoLevitate" >= 10 )
				DisableLevitation
			endif
		endif
		set bountySave to GetPCCrimeLevel
		SetPCCrimeLevel 0
		set inEffectsZone to 1
	endif
else
	if ( li_g_islandDistance > 25100 )		; player leaves the island zone
		EnableTeleporting
		EnableLevitation
		SetPCCrimeLevel bountySave
		set inEffectsZone to 0
	endif
endif

; journal entries when you've experienced the levitation / teleport ban
if ( inEffectsZone == 1 )
	if ( player -> GetEffect sEffectLevitate )
		if ( li_g_islandRuin < 4 )
			if ( GetJournalIndex "LI_J_NoLevitate" < 10 )
				if ( GetJournalIndex "LI_J_info_children" < 20 )
					Journal LI_J_NoLevitate 10
				else
					Journal LI_J_NoLevitate 15
				endif
				DisableLevitation
			endif
		endif
	endif
	if ( player -> GetEffect sEffectMark )
		set teleportSpell to 1
	elseif ( player -> GetEffect sEffectRecall )
		set teleportSpell to 2
	elseif ( player -> GetEffect sEffectAlmsiviIntervention )
		set teleportSpell to 3
	elseif ( player -> GetEffect sEffectDivineIntervention )
		set teleportSpell to 4
	endif
	if ( teleportSpell > 0 )
		if ( li_g_islandRuin == 0 )
			if ( GetJournalIndex "LI_J_NoEscape" == 0 )
				Journal LI_J_NoEscape 10
			elseif ( GetJournalIndex "LI_J_NoEscape" == 20 )
				Journal LI_J_NoEscape 30
			elseif ( GetJournalIndex "LI_J_NoEscape" == 22 )
				Journal LI_J_NoEscape 30
			elseif ( GetJournalIndex "LI_J_NoEscape" == 40 )
				Journal LI_J_NoEscape 50
			endif
		elseif ( li_g_islandRuin < 9 )
			if ( teleportSpell > 1 )
				if ( teleportMsg == 0 )
					MessageBox "Teleportation starts to work now... though not very reliably."
					set teleportMsg to 1
				endif
				; delay random teleport script by one frame due to a strange crash bug
				set randomTeleport to 1
			endif
		endif
		set teleportSpell to 0
	endif
endif

; if you've found the island on your own...
if ( GetJournalIndex "LI_J_LothIsland" < 10 )
	if ( li_g_islandDistance < 10000 )
		if ( GetJournalIndex "LI_J_Ragnar" == 5 )
			Journal LI_J_LothIsland 12
		else
			Journal LI_J_LothIsland 11
		endif
		StartScript li_setInitialDispositions
		StartScript li_islands_grip_buildup
		StartScript li_dreamTracker
		StartScript li_QuestScheduler
		li_torlof_sigurdsson -> Disable
		li_longboat02_sadrith -> Disable
		li_boatplank_sadrith -> Disable
	endif
endif

; start relationship tracker script
if ( li_g_playerMate == 0 )
	if ( GetJournalIndex "LI_J_LothIsland" >= 20 )
		if ( li_g_PCSex == 0 )
			if ( ScriptRunning "li_RelationshipTracker_m" == 0 )
				StartScript li_RelationshipTracker_m
			endif
		elseif ( li_g_PCSex == 1 )
			if ( ScriptRunning "li_RelationshipTracker_f" == 0 )
				StartScript li_RelationshipTracker_f
			endif
		endif
	endif
endif

; checks whether the player is detected by anyone
; GetDetected is a slow function, store it for further use in conjunction with GetLOS for each NPC
set timer1sec to timer1sec + GetSecondsPassed
if ( timer1sec >= 1 )
	set li_g_gotDetected to GetDetected, player
	set timer1sec to 0
endif

; frame counter blocking sleep combat refresh for 3 frames
set temp to li_g_noSleepCbt
if ( temp > 0 )
	set temp to temp + 1
	if ( temp > 3 )
		set temp to 0
	endif
	set li_g_noSleepCbt to temp
endif

; effects with strong Berserk Fury spell
if ( playerBerserk == 0 )
	if ( player -> GetSpellEffects "li_berserk_fury_uber" == 1 )
		PlaySound "were roar"
		set exhaustTime to 10.0
		set playerBerserk to 1
	endif
else
	if ( player -> GetSpellEffects "li_berserk_fury_uber"  == 0 )
		set exhaustTime to exhaustTime - GetSecondsPassed
		if ( exhaustTime > 0 )
			set temp to -20.0 * GetSecondsPassed
			player -> ModCurrentFatigue temp
		else
			set playerBerserk to 0
		endif
	endif
endif

; swap your rival's key in your inventory to a more descriptive one
; (RemoveItem is buggy with scripted items, so it has to be done here)
if ( player -> GetItemCount "li_key_sanctdoor1" > 0 )
	if ( MenuMode == 0 )
		player -> RemoveItem "li_key_sanctdoor1", 1
		player -> AddItem "li_inv_key_fight", 1
	endif
endif

; store player's current cell code (for DreamTracker and AI scripts)
if ( GetInterior == 0 )
	set li_g_currentCell to 0
elseif ( GetPCCell "Heralds' Haven, Guest Tower" )
	set li_g_currentCell to 10
elseif ( GetPCCell "Heralds' Haven, Manor" )
	set li_g_currentCell to 11
elseif ( GetPCCell "Heralds' Haven, Men's Quarters" )
	set li_g_currentCell to 12
elseif ( GetPCCell "Heralds' Haven, Women's Quarters" )
	set li_g_currentCell to 13
elseif ( GetPCCell "Heralds' Haven, Quarters Passage" )
	set li_g_currentCell to 14
elseif ( GetPCCell "Heralds' Haven, Cellars" )
	set li_g_currentCell to 15
elseif ( GetPCCell "Heralds' Haven, Lighthouse" )
	set li_g_currentCell to 16
elseif ( GetPCCell "Fort Forcewell, Study" )
	set li_g_currentCell to 20
elseif ( GetPCCell "Fort Forcewell, Northern Guardhouse" )
	set li_g_currentCell to 21
elseif ( GetPCCell "Fort Forcewell, Southern Guardhouse" )
	set li_g_currentCell to 22
elseif ( GetPCCell "Fort Forcewell, Sanctuary Entrance" )
	set li_g_currentCell to 23
elseif ( GetPCCell "Fort Forcewell, Sanctuary Caves" )
	set li_g_currentCell to 24
elseif ( GetPCCell "Fort Forcewell, Sanctuary Spine" )
	set li_g_currentCell to 25
elseif ( GetPCCell "Fort Forcewell, Passage Cave" )
	set li_g_currentCell to 26
elseif ( GetPCCell "Aurora Isle, Dock Shack" )
	set li_g_currentCell to 30
elseif ( GetPCCell "Aurora Isle, Ancient Tomb" )
	set li_g_currentCell to 31
elseif ( GetPCCell "Aurora Isle, Underwater Caves" )
	set li_g_currentCell to 32
elseif ( GetPCCell "Aurora Isle, Maze of Lost Souls" )
	set li_g_currentCell to 33
else			; unknown interior
	set li_g_currentCell to 99
endif


; provides a safe way to disable saving by changing the CharGenState variable
; that shouldn't conflict with other mods that do the same
;	GLOBAL short li_g_savingDisabled
;	GLOBAL short li_g_CGS_backup

; enable saving immediately when you switched savegame restrictions off
if ( li_g_saveAlways )	
	if ( li_g_savingDisabled == 1 )
		set li_g_savingDisabled to 0
	else
		return		; otherwise, skip the rest of the script
	endif
endif

if ( li_g_savingDisabled == 1 )
	if ( saveDisableDone == 0 )		; saving has just been disabled
		if ( CharGenState != -1 )		; another mod has changed CharGenState
			set li_g_CGS_backup to CharGenState
			set CharGenState to 99
		else
			set CharGenState to 99
			EnableStatsMenu		; only restore menus when they weren't disabled by the other mod as well
		endif
		set saveDisableDone to 1
	else									; monitor other mods' activity while saving is disabled
		if ( CharGenState != 99 )		; another mod has changed CharGenState
			set li_g_CGS_backup to CharGenState
			set CharGenState to 99
			if ( li_g_CGS_backup == -1 )		; only restore menus when "allowed" by the other mod
				EnableStatsMenu
			endif
		endif
	endif
	return
else
	if ( saveDisableDone == 1 )		; saving has just been re-enabled
		if ( li_g_CGS_backup != 0 )
			set CharGenState to li_g_CGS_backup
		else
			set CharGenState to -1
		endif
		set li_g_CGS_backup to 0
		set saveDisableDone to 0
	endif
endif

End
2) that damn shark
There is a shark in the cave. You are supposed to lure it out but it is stuck. Ignore it and TCL trough doors that won't open.

3) party
GetPosition does not work as intended again. To dance with your partner TCL and go INSIDE model. Then script should pick it up.

4) last key
main script again. Just add it with console player -> AddItem "li_inv_key_fight", 1

5) Always closing doors
This is in the spine sanctuary.

Code: Select all

Begin li_spinedoor_spellguard

short unlocked
short firstframe

; to avoid message boxes on entering cell for the first time
if ( firstframe == 0 )
	if ( unlocked == 0 )
		Lock 0
	endif
	set firstframe to 1
	return
endif

if ( unlocked == 0 )
	if ( GetLocked == 0 )
		Lock 0
		MessageBox "The lock immediately snapped shut again."
	endif
endif

End
No idea what the heck Lock 0 is supposed to do. Just tcl and lock 5 every single iron bar doors. Later one pressing switch will unlock those as normal.

User avatar
akortunov
Posts: 439
Joined: 13 Mar 2017, 13:49
Location: Samara, Russian Federation
Github profile: https://github.com/akortunov

Re: lothavor's legacy

Post by akortunov » 09 Oct 2017, 06:53

sirherrbatka wrote:
09 Oct 2017, 06:29
No idea what the heck Lock 0 is supposed to do.
IIRC, in vanilla Morrowind "lock 0" locks a door, but the door tooltip will not have the "Locked" label. GetLocked in this case will return 1.
Also any "lock" command sets the door animation state to the "Closed". It seems this script is supposed to keep a door always closed till unlocked == 0.

In OpenMW "lock 0" does not change a lock level, so there is a bug.
Also OpenMW treats a door with 0 lock level as opened, so we can not just change lock() function (as I wanted to do).
I guess that Morrowind has a locked state variable (opened/locked/unlocked), separate from the lock level.
Last edited by akortunov on 09 Oct 2017, 08:35, edited 5 times in total.

User avatar
akortunov
Posts: 439
Joined: 13 Mar 2017, 13:49
Location: Samara, Russian Federation
Github profile: https://github.com/akortunov

Re: lothavor's legacy

Post by akortunov » 09 Oct 2017, 07:07

sirherrbatka wrote:
09 Oct 2017, 06:29
2) that damn shark
There is a shark in the cave. You are supposed to lure it out but it is stuck. Ignore it and TCL trough doors that won't open.
Can you describe what do you mean? Does an engine spawn the shark inside other object? Or does the shark have a big collision box, so it can not swim inside a narrow cave passage?

User avatar
sirherrbatka
Posts: 2121
Joined: 07 Aug 2011, 17:21

Re: lothavor's legacy

Post by sirherrbatka » 09 Oct 2017, 10:08

It seems this script is supposed to keep a door always closed till unlocked == 0.
Yeah, that's my guess.
Can you describe what do you mean? Does an engine spawn the shark inside other object? Or does the shark have a big collision box, so it can not swim inside a narrow cave passage?
Shark has big collision box, and it is unable to move in this cell. I tried to spawn it with placeatpc while midair. Shark gracefully hits the water, but it is unable to move afterward anyway (even if it looks like it should).

User avatar
akortunov
Posts: 439
Joined: 13 Mar 2017, 13:49
Location: Samara, Russian Federation
Github profile: https://github.com/akortunov

Re: lothavor's legacy

Post by akortunov » 09 Oct 2017, 16:37

sirherrbatka wrote:
09 Oct 2017, 10:08
Shark has big collision box, and it is unable to move in this cell. I tried to spawn it with placeatpc while midair. Shark gracefully hits the water, but it is unable to move afterward anyway (even if it looks like it should).
Even more strange: the shark can move on the ground (placeatpc), but can not move underwater.

User avatar
sirherrbatka
Posts: 2121
Joined: 07 Aug 2011, 17:21

Re: lothavor's legacy

Post by sirherrbatka » 09 Oct 2017, 18:50

Not exactly move. It just falls down.

User avatar
Kloppix
Posts: 32
Joined: 24 Mar 2014, 14:41

Re: lothavor's legacy

Post by Kloppix » 29 Sep 2018, 13:23

I’m playing Lothavor's Legacy right now. I will try to post some workarunds as I discover them.

Diane’s swimming race:
Problem: (?)
According to the script "li_AI_i_Diane_race1", the function AIActivate was buggy in Morrowind so he putted several activators ouside their cells. It seems OpenMW don’t like this hack.

1) Speak with Diane at the island and start the race.
When Diane suddenly stops type in the console: "lc_diane -> AIActivate li_wp110_2"
When she stops again: "lc_diane -> AIActivate li_wp110_3"
and again: "lc_diane -> AIActivate li_wp110_4"

2) Won the race. Is easy if you drop all your heavy stuff before starting. If you don't become the message "- you have won the race -" load a previous game and try again.

3) Type in the console:
lc_diane -> AIWander 0 0 0 20 0 0 0 0 0 0 0
lc_diane -> ClearForceRun
lc_diane -> SetSpeed 60
lc_diane -> SetAthletics 48

4) Assuming you didn’t cheat (because role-playing reasons):
set lc_diane.greetingCode to 111
set li_AI_i_Diane_race1.state to 5

5) Go close to Diane.


The Shark (that damn)
Problem:
As Sirherrbatka said. It doesn’t move. I tried putting him in the ocean, using command spells, AiFollow function,… nothing works.

Open the console, click on him and type “setpos x -2000”

Final battle
When you win the battle a second enemy should die. Just click on it and type “sethealth 0”. It's not necesary but it gives a nice loot.

I did the party and the locking locks Sirherrbatka’s way. Thank you. I didn’t have any issues with the last key.

OpenMW 0.44 in Debian

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests