Morrowind Mod:Scripts from LofZ

The UESPWiki – Your source for The Elder Scrolls since 1995
Jump to: navigation, search
This page or section is incomplete. You can help by adding to it.
For more information, see the help files, the style guide, and this article's talk page.

Foreword[edit]

This is a compilation of scripts made by LofZ from 2006 to 2009, supplemented with detailed instructions and often possible applications. Included also are a few scripts suggested by other people in discussion threads as alternatives. There are also a few modified scripts from original game and by other modders. Please note that more effective solutions for the described situations may already exist, and yet everything here works just as it did five or more years ago.

Supplementary texts were translated from Russian and hosted here together with scripts with gracious permission of LofZ.

A little info about the author (based on the clues which were gathered from Russian sites): LofZ, a.k.a. Deska, was very active on the Morrowind modding scene since at least 2005 until 2013. She generously donated her time to the community, writing a large number of tutorials and "how-to" threads, which as of now were viewed several tens of thousands times in the aggregate. She created many quest mods, herself or in collaboration with the group of modders called "Dreamers guild". Unfortunately none of her mods were ever translated. LofZ is also an author of several Morrowind fanfics.

Scripts with different outcomes depending on a player character's sex[edit]

Defining a PC's sex is possible only through a dialogue. You probably know about two functions, PC Sex and Same Sex, which can be used to create phrases only for PCs-gals or PCs-guys.

The good news is that you can still create a situation where certain events take place depending on a character's sex. It is possible to force the CS "see" a PC's sex and use this information in scripts. For example, let's create a cuirass (aaaa_cuirass), which a male PC can equip easily, while a female will have problems with it.

You can do this by adding a script to the cuirass, which will check a PC's sex on equipping it, so that a woman would get cursed (for instance), but a man wouldn't.

Still we can't do without dialogues, and will have to make a PC talk to somebody. So let's go ahead and create a new NPC for the dialogue, or just use some of the stock ones. Go to the "global" tab and create a new global variable of the "short" type called aa_PCSex and the initial value of 0. Then create two new phrases for the NPC in the "dialogue" window. Write the first phrase, addressed to a male character: "Here is your new cuirass: fancy, yet sturdy. Wear it with honor." In "results" field type: player->additem "aaaa_cuirass" 1. Above it add the second phrase, this time for a female character: "Here is your cuirass. Too bad it is enhanced and you can't wear it. But at least you can present it to a friend". The condition for this phrase would be: function->PC Sex==1. Write this in the results:

Player->additem "aaaa_cuirass" 1
Set aa_PCSex to 1

You can take several measures to prevent the NPC from giving away cuirasses every time they are talked to. One way is to add a journal entry, which will be updated when the cuirass is given out, and write the third phrase above with condition on this journal entry. The other way is to attach a script with some local variable to the NPC, which will change its value as a result of "cuirass handing out" phrase; then create a new phrase above with this variable value as condition. Finally, you can attach to the NPC a script with "disable" and make them disappear at the end of the dialogue. But I shouldn't go into such details here, just as I shouldn't explain who this strange guy was and why he handed out such unique cuirasses.

What really matters is that we got a global variable aa_PCSex, which has different values depending on character's sex: 0 if lad, 1 if lass.

Thus, while you have this global variable, you are able to create scripts with different outcomes depending on a character's sex, by adding conditions "if ( aa_PCSex==1 )" or "if( aa_PCSex==0 )" to them.

NPC forcegreeting[edit]

Forcegreeting is a command which forces an NPC to speak to a player character first.

It is usually used for two reasons:

1. To increase a level of tension of the scene. If an NPC hurries to say something to a player character, not waiting to be addressed as usual, then something urgent has happened.

2. To protect an NPC if there is a danger that they will be accidentally killed.

For instance, in an underwater grotto among multitude of dreughs there is one ancient specimen that can communicate using telepathic powers and should give a quest to the protagonist. But the player doesn't know that it is not dangerous, and rather have the Nerevarine raise their sword than speak with it. Forcegreeting is very useful here – it immediately gives the idea of importance of this particular dreugh.

If you use forcegreeting, I recommend you to supplement it with sounds or "say" command.

The forcegreeting command is usually invoked by distance condition, i.e. distance between the protagonist and NPC or other object:

if ( GetDistance, Player < 700 )
forcegreeting
endif

The most common mistake here is that script gets caught in an endless loop. The conditions are met every frame (PC is near the object), and every second a new dialogue window pops up. This leads to MW hanging. This is why it is advisable to introduce a new short variable:

begin razgovor
; by LofZ

short once 

if ( Menumode == 1 )
return
endif

if ( once == 0 )
if ( GetDistance, Player <= 512 )
forcegreeting
set once to 1
endif
endif

end

Note on distance:

250 and less is approximately the length of a stretched arm, or even closer.

512 is several steps. This is standard distance and fits for a situation when an NPC greets a player character walking nearby.

700 and more will suit better if an NPC calls for help from afar.

1000 is too much. An NPC practically cannot be seen. This, combined with the element of surprise, usually irritates people.

Land features play a role here, and may prevent forcegreeting if an NPC can't see the character.

So every NPC with such a script will greet the protagonist the second they fulfill the distance condition. Here is a caveat: a modder who adds several NPCs with forcegreeting in one cell expects them to work one after another. But it will happen this way only if one NPC is near the player character, while another one is further, much further away. So, if you don't add additional elements, it's not so easy to foresee how close NPCs will be to PC, and most often both (if you have used two) forcegreeting scripts will work simultaneously. This will produce a very ugly effect: both replies will be in one window. This looks very untidy and worsens a player's experience.

So if you want to start several forcegreetings in order, include a script with a timer in one of them:

begin lofZ-at

; compiled by LofZ

float timer

if ( MenuMode == 1 )
Return
endif

if ( once == 1 )
return
endif


if ( once == 0 )
if ( GetDistance, Player < 1000 ) ; or any other condition that may cause commands to clash

set timer to timer + GetSecondsPassed
endif
if ( timer > 2 ) ; the time can be changed
forcegreeting

set once to 1
endif
endif

end

By the way, the timer here will continue to count out, even if the dialogue window is open. This means that if you choose to start a second dialogue in 20 seconds rather than 2, the second window may still open just after the first one is closed, if the first one is kept opened long enough.

Still, even if the first window is opened for a long time, and the time for the second one is already run out, there won't be any clashing, as they will be opened in order. So even such small interval as 2 seconds is enough for dialogues to start one after another, and not at once.

Also, don't forget to take care about what NPCs will actually say, this is more important for daedra and animals – they don't have greetings, nor topics.

Scripts for messages with comments on objects[edit]

If you need to give a player additional information about an object, attach to it one of the following scripts (don't forget to create a new object with unique ID!):

1. Every time a character touches the object, a player sees a box with a message.

begin Comment

; compiled by LofZ

if ( MenuMode == 1 )
return
endif

if ( OnActivate == 1 )
MessageBox "The door is blocked and won't open"
return
endif

end

Note: the object with this script attached can't be picked up. If it is a door – it won't teleport you into other room. If it is an NPC, it can't be talked to.

2. The same effect, but the character can take the object or talk to NPC.

begin Comment_A

; compiled by LofZ

if ( MenuMode == 1 )
return
endif

if ( OnActivate == 1 )
MessageBox "It's just an old jug covered in dust, and its bottom is missing. Why have you picked it?"
Activate
endif

end

3. The commentary will show up only the first time, then you can pick up the object.

begin Comment_B

; compiled by LofZ

short once

if ( MenuMode == 1 )
return
endif
if ( once == 1 )
return
endif

if ( once == 0 )
if ( OnActivate == 1 )
MessageBox "You see a stolen Temple ring on J'Tirr's finger. The Khadjit pretends he doesn't see you and makes every effort to escape the conversation"
set once to 1
endif
endif

end

4. The character needn't touch an object for the extra information window to appear. This way you may add messages, describing condition of walls, windows, various rocks, houses and bed-boxes etc. The script can be attached to any object which allows it, such as a light, and will take place only once.

begin Comment_C

; compiled by LofZ
short once 

if ( MenuMode == 1 )
return
endif

if ( once == 1 )
return
endif

if ( once == 0 )
if ( GetDistance, Player <= 300 )
MessageBox "Suddenly you sense a pleasant aroma of freshly baked bread"
Set once to 1
endif
endif

end

Protection of especially important NPC[edit]

If an NPC is very dear to you, and you don't want a player to kill them (this is relevant if you plan on making an avatar of yourself or your friend), there are several ways to protect them.

1. The most economical one: just tick one of these boxes in the object properties:

a) Essential – if an NPC or a creature dies, the familiar phrase will be displayed: "With the death of this character..." A player will think that maybe their Nerevarine career is worth more than the life of this creature.

b) Respawn – the creature can be killed, but after 72 hours (by default) it will be resurrected. Suits for some situations.

2. Through script:

a) Make an NPC invincible or resurrect it. (Sorry, the links for these were dead - MWM wiki.)

b) Use a special script which will kill a character if the NPC was attacked:

Begin VainlyYouAttack

; compiled by LofZ
if ( Menumode == 1 )
return
endif

if ("aa_azura"->GetAttacked == 1 )
Player -> sethealth 0 
endif

end

Be careful though: position the NPC (aa_azura in this case) in a place where only a player character could harm them. If they are attacked by some cliff racer or an ordinator, who actually came after a PC, the latter will instantly die.

The global timer script with an event at the end[edit]

1. Create a new journal entry ("aaa_note") and make a note for it with index 1. This would be the note after which the timer starts. For example: "She said I shouldn't worry and continue my journey. She will find me herself after several days."

2. Write a new script in the editor, like this:

begin AA_global_time2

short daysPassed
short myDay
short state
; compiled by LofZ
if ( daysPassed == 0 )
set myDay to Day
set daysPassed to 1
endif

if ( myDay != Day )
set daysPassed to daysPassed + 1
set myDay to Day
endif

if ( GetPCSleep == 1 )
if ( state == 0 )
if ( GetJournalIndex "aaa_note" == 1 )
if ( daysPassed >= 3 ) ; quantity of days can be changed.
WakeUpPC
placeatpc "aa_mephala" 1 128 1
set state to 1
endif
endif
endif
endif

if ( state == 1 )
stopscript "AA_global_time2"
endif

end

Note: the script won't compile at first. The problem here is that it is not present in registry yet, and the editor would think that it doesn't have anything to stop.

Cut this fragment (ctrl-x):

if ( state == 1 )
stopscript "AA_global_time2"
endif

Save the script, then insert everything back using ctrl-v and save again.

3. You can add a message box after WakeUpPC line with contents like: "You've been dreaming of..."

Launch a new script. Do this by typing journal"aaa_note" 1 "startscript "AA_global_time" in dialogue results. (I recommend you to use some original theme, and not stock Morrowind one.)

Don't confuse local variable DaysPassed, used in this example, with global variable DaysPassed, introduced by Tribunal.

The script which restricts PC's movement[edit]

This script – the result of Daedra lord Mephala's curse – punishes a PC for entering the cells you have added to it. If they show up there, they will die.

1. Create a new journal note "1a_end" with an index 10, which should stop the script (I was able to lift a curse of Mephala. Now I can walk in Morrowind wherever I please.)

2. Start a global script:

begin LofZ-TerribleDeath

short once

if ( menumode == 1 )
return
endif

if ( GetJournalIndex "1a_end" >= 10 )
stopscript "LofZ-TerribleDeath"
return
endif

if ( once == 0 )
if ( getPCCell "Molag Mar" == 1 )
player->sethealth 0 
MessageBox "The Mephala's curse was not strong enough to kill you when you came out of the mine. Her magic works in a different way. 
It kills you only when you enter a certain city. Now you know it, but it is too late..."
set once to 1
endif
endif
if ( once == 0 )
if ( getPCCell "Sadrith Mora" == 1 )
player->sethealth 0 
MessageBox "The Mephala's curse was not strong enough to kill you when you came out of the mine. Her magic works in a different way. 
It kills you only when you enter a certain city. Now you know it, but it is too late..."
set once to 1
endif
endif
if ( once == 0 )
if ( getPCCell "Balmora" == 1 )
player->sethealth 0 
MessageBox "The Mephala's curse was not strong enough to kill you when you came out of the mine. Her magic works in a different way. 
It kills you only when you enter a certain city. Now you know it, but it is too late..."
set once to 1
endif
endif

if ( once == 0 )
if ( getPCCell "Vivec" == 1 )
player->sethealth 0 
MessageBox "The Mephala's curse was not strong enough to kill you when you came out of the mine. Her magic works in a different way. 
It kills you only when you enter a certain city. Now you know it, but it is too late..."
set once to 1
endif
endif
if ( once == 0 )
if ( getPCCell "Ald-ruhn" == 1 )
player->sethealth 0 
MessageBox "The Mephala's curse was not strong enough to kill you when you came out of the mine. Her magic works in a different way. 
It kills you only when you enter a certain city. Now you know it, but it is too late..."
set once to 1
endif
endif

end

Notes:

Script doesn't compile at first, because it is not present in the registry yet. The editor thinks it has nothing to stop.

Cut this fragment (ctrl-x):

if ( GetJournalIndex "1a_end" >= 10 )
stopscript "LofZ-TerribleDeath"
return
endif

Save the script, then insert the cut section back using ctrl-v and save again.

Add or remove cells if you want to. This way, you can restrict a PC from visiting various towns or even interiors.

Don't forget to create an actual quest and activate "1a_end" 10 at its end, otherwise the Nerevarine won't be able to travel freely across the game world anymore.

Script which adds journal notes[edit]

This script is attached to an object. Once it is activated, the journal is updated once. The object can be used later again.

1. Create a new journal note with required index (journal "1a_map" 12 in this example).

2. Use this script:

begin L_forMap

short once 


if ( once == 0 )
if ( OnActivate == 1 )
journal "1a_map" 12
activate
set once to 1
endif
endif

if ( once == 1 )
if ( onActivate == 1 )
activate
endif
endif

end

Now where were I yesterday?[edit]

I suggest this script for situations when a PC needs to be knocked unconscious. The script should be attached to an object. On activation, the poor Nerevarine is kicked into other cell, and exactly one day passes. In other words, after some manipulations with an object, they regain their senses in unknown place the day later.

begin Lo_xaos
; Автор - LofZ
short once

if ( menumode == 1 )
return
endif

if ( OnActivate == 1 )
fadeout 2
FadeIn 2

set Day to (Day + 1)
journal "aaa_ujos" 10
Player -> PositionCell 583, -386, -1529 0 "Pelagiad, South Wall"


set once to 1

endif
endif

if ( once == 1)
disable ; the object needs to be deleted, so that amnesia won't happen again
endif
if ( GetDisabled == 1 )
setdelete 1
return
endIf 

end

Note: a line "journal "aaa_ujos" 10" is not necessary. This is just a journal note telling about the feelings of the character. If you need it, go ahead. Note with index 10 may have following contents: "I emptied a pint of mazte in the tavern, but what happened next is complete mystery".

Poisonous candles (a trap for vampires)[edit]

This script creates a sort of a trap for a vampire character. When in interior containing an object with this script attached, such character gets hurt. The script is used in our plugin "Shadows before the dawn". There was a magical illumination with a daylight effect, disastrous for vampires. The script has lots of potential: one can create traps in labyrinths and so on.

begin L-candle

short once
float timer
float damage
; compiled by LofZ
If ( menumode == 1 )
Return
Endif

if ( PCVampire != 1 )
return
endif


if ( PCVampire == 1 )
if ( once == 0 )
set once to 1
endif
endif

if ( once == 1 )
set damage to -10
set damage to ( damage * GetSecondsPassed )
messagebox "These candles emit a very bright light. It burns your skin."
Player->ModCurrentHealth, Damage
set once to 2 
endif

if ( once == 2 )
set timer to ( timer + GetSecondsPassed )
endif
if ( timer >= 3 )
set once to 0 
endif
end

Stop the fight[edit]

I will tell you how to stop NPC fighting a player character and make them beg for mercy. You can use it in quests involving duels or the pacifying of enraged alcoholics.

1. Create a new NPC and write a dialogue for them: add a new journal note (aaa_draka in my example), where it is especially important to write a phrase with their plea for mercy, and an index for it. Then write greetings for the aggressor, or topics, if necessary.

Example:

a) Create a journal note aaa_draka: "I have been assaulted". Set index 1 for it.

b) Write a greeting for the attacking NPC: "Now I will beat you badly"

c) Write in dialogue results:

"aaa_draka" 1
startcombat, Player
goodbye

2. Use the following script on an NPC:

Begin Fight

short nolore 
; most standard topics, like "my trade" and "little advice" are for the good-natured, so we should block them for our villain.

if ( MenuMode == 1 )
Return
endif

if ( GetJournalIndex "aaa_draka" >= 15 )
return
endif
; the script is not needed, if the fight has already took place. 

if ( GetJournalIndex " aaa_draka " == 1 ) 
if ( GetHealth <= 50 )
say, "vo\d\m\Fle_DM004.mp3", "Spare me!"
stopcombat, Player 
forcegreeting 
setdisposition 50
setfight 30 
endif
endif

End

The conditions here dictate that when NPC's health drops below 51 (but only in this scripted situation; if you just start beating them, they won't cry for mercy), they scream and stop fighting. For the increased effect, a sound of screaming is played out (in this case belonging to a Dunmer male, but you can use any custom file).

Don't forget to add index 15 for aaa_draka with the following contents: "They pleaded for mercy".

In the greetings of the attacking NPC write the phrase: "Spare me!" with condition: journal aaa_draka 1.

Write in its results:

"aaa_draka" 15
stopcombat, Player
Goodbye

2nd line is a safety measure; there are reports that sometimes an NPC stops fight only for one frame, and then continues, if only the script or the dialogue command was used.

A duel with an NPC with unusual ending[edit]

The tournament duels with NPCs are frequent in Morrowind. They invariably end with NPC's plea of mercy, when their health reaches a certain threshold. Boring, isn't it? Thankfully, you can spice this up, and without much effort. I will tell you how to create an alternative variant, so that in battle not only the battered opponent cries for mercy, but also a player character, when wounded, is mocked at, humiliated and is demanded to beg for pardon. Here is the procedure:

1. Create an enemy combatant with more than 50 hit points and place them in the game. In my example it would be a Nord bully called aa_mantas. Not a bright fellow, but still has a certain charm. He is called after annoying monsters from Fallout and behaves accordingly.

2. Create a new note for the journal, "aaa_zadira" (bully in Russian) and add to it TopicInfos like below, with the following indices:

The first entry should be "The Bully" with Quest Name box ticked.

20 – I was attacked by some strange Nord.

89 – I have lost this battle.

30 – we have settled our quarrel – I have beaten the bully.

95 – I have killed the offender.

90 – the offender decided to spare me.

Tick Finished box on the last three TopicInfos.

3. Attach the following script to the offender:

begin neuvazhay_koryto
; compiled by LofZ
short once 

if ( Menumode == 1 )
return
endif

if ( GetJournalIndex "aaa_zadira" >= 30 )
return
endif

if ( GetHealth <= 0 )
journal "aaa_zadira" 95
endif

if ( once == 0 )
if ( GetDistance, Player <= 350 )
forcegreeting
set once to 1
endif
endif

if ( once == 1 )
if ( GetHealth, "aa_mantas" < 50 )
say, "vo\n\m\Hit_NM005.mp3", "groan" ;  nord's voice
stopcombat 
forcegreeting
SetFight 30
set once to 2
endif
endif

if ( once == 1 )
if ( Player -> GetFatigue <= 0 )
if ( Player -> getHealth <= 20 )
say, "vo\n\m\Fle_NM004.mp3", "The battle is over, I am going away" ; what else could he say anyway?
journal "aaa_zadira" 89
stopcombat 
SetFight 30
forcegreeting
set once to 2
endif
endif
endif

end

Note the lines:

if ( Player -> GetFatigue <= 0 )

if ( Player -> getHealth <= 20 )

First, you can modify these values, setting condition for fatigue and health of a PC. (20 is not much, of course – the PC is almost killed. If the opponent is too strong, he can kill the poor Nerevarine and the dialogue won't take place.)

Second, and the most important, sufficiently levelled PC is difficult to exhaust, and the condition if ( Player -> GetFatigue <= 0 ) may never trigger. If your quest is aimed at a seasoned character, pick a different fatigue value, or even remove it altogether.

4. Write a greeting for the aggressor with condition journal "aaa_zadira" < 20 and contents like this:

"I will show you your place, %PCRace! I won't kill you, just dip you in the mud a little and see what color your blood is!"

Write the following in the results:

journal "aaa_zadira" 20
startcombat, player
goodbye

5. Now create the next greeting above with condition journal "aaa_zadira" == 20 and write a reply our bully will say when defeated: "Hold your hand! You have won. Here, take some gold, buy yourself a drink and forgive me."

In results:

player -> additem "gold_001" 50
journal "aaa_zadira" 30
stopcombat 
goodbye

6. Finally, write another greeting, describing the most interesting situation – PC's defeat, with condition journal "aaa_zadira" == 89. Here is an example phrase: "Is it enough for you, %PCRace? I have defeated you, fairly! Now go lick up your wounds and remember that I could kill you, but spared of death. Not every opponent you encounter here is so generous!"

In conditions:

journal "aaa_zadira" 90
goodbye

7. If the NPC was killed despite everything, the system automatically responds with adding a new journal entry with index 95.

That's it. Write a new dialogue for the bully if you want to. Save the plugin and enjoy the game.

Adding items, renew traders' inventories[edit]

This global script adds a new object to the game world and to the inventory of several NPCs, three days after game is started. It was used in plugin "Nocturnal's gift", where it adds the latest issue of "The Long Tongue" magazine (a_bk_Dl-f) featuring an interview with the Nerevarine. The script actually has a lot of potential. One can add practically anything anywhere, with a few modifications. For instance, it's possible to alter the assortment of traders' goods globally.

begin L-DF

short daysPassed
short myDay
short state


if ( daysPassed == 0 )
set myDay to Day
set daysPassed to 1
endif

if ( myDay != Day )
set daysPassed to daysPassed + 1
set myDay to Day
endif


if ( state == 1 )
stopscript "L-DF"
return
endif

if ( state == 0 )
if ( daysPassed >= 3 )
PlaceItemCell "a_bk_Dl-f" "Vivec, Black Shalk Cornerclub" 454, -142, 2 0 
PlaceItemCell "a_bk_Dl-f" "Vivec, Elven Nations Cornerclub" 6, -332, -190 0
PlaceItemCell "a_bk_Dl-f" "Vivec, The Flowers of Gold" -54, 99, -62 0
PlaceItemCell "a_bk_Dl-f" "Vivec, The Lizard's Head" 346, -70, -63 0
"jeanne"->additem "a_bk_Dl-f" 1
"jobasha"->additem "a_bk_Dl-f" 2 ; Gives Jobasha two issues, just because. 
"simine fralinie"->additem "a_bk_Dl-f" 1
"tervur braven"->additem "a_bk_Dl-f" 1

set state to 1
endif
endif
endif

end

To prevent your new object from appearing somewhere under the floor or flying in the air, it's better to place it in the cell first, put down coordinates for the script to use, then delete the object and clean the location with TESAME.

Disappears at nights...[edit]

The object this script is attached to looks normal at day, but disappears at night (being disabled).

begin L-BrineDisable

;  made by LofZ

if ( menumode == 1 )
return
endif

if ( Gamehour >= 0 )
        if ( Gamehour  < 6 )
                if ( "object's ID"->getdisabled == 0 ); so that disable was performed only once
                        "object's ID"->disable
                endif
else
        if ( "object's ID"->getdisabled == 1 ); so that enable was performed only oncem and not every frame
                "object's ID"->enable
        endif
        endif
endif

end

Enter your object's ID in the brackets. We used this script in a plugin about one not really bright guy, called Brine (aa_brine). This fellow went out of town at nights, but was back by day. Accordingly, the lines with commands were like this: "aa_brine"->disable etc.

Practice dummy[edit]

Here I will show you how to make a practice dummy which can be really used for training. It can be hit, and if a PC does it frequently, their skills will improve.

The idea is drawn from the plugin "Japanese house".

In a nutshell, we need to create a new invincible character of a new race.

1. Unpack Morrowind.bsa using bsa unpacker, and take furn_practice_dummy.nif file. It is located in Meshes\f folder.

2. Create the folder "f" in Data Files\meshes folder and copy this file there. The file is actually a model of a training dummy. It has associated textures, but you don't need to extract them, as they will be automatically loaded from .bsa archive of the game.

Now there is some work to do in the CS:

1. Create a new race (Character->Race->New) with ID, say "1a_model" and name "Mannequin". Set zeroes for all base attributes. Description and Skill Bonuses are not needed, but you can fill them if you want to. Set both height and weight to 1.0 for both genders. Don't tick any boxes.

2. Now, if our practice dummy is to fulfill its purpose, it needs invincibility. You can do that using a special spell. Go to Spellmaking tab. Create a new spell with health restoration effect, area – 0, duration – 1, with values from 2000 to 2500. Choose type "ability". Check always succeeds box. Add this spell to the new race (you can do this by dragging it from Spellmaking to the properties of the new race).

3. Now you need to link body parts models for the new race. Go to body part tab and create a body part with a new ID for our race. These are the parameters: Part->Groin; Part type->Skin; Type->Normal. Don't tick female box, as our mannequin will be male. Press Add art file button and link the part to the model furn_practice_dummy.nif, i.e. C:\Program Files\Bethesda Softworks\Morrowind\Data Files\Meshes\f, if you have chosen the default installation path.

4. Now let's start creating our practice dummy. Go to NPC tab and create a new character of the new race (1a_model) with a new ID, "Training Dummy". Choose any class and level, though it's easier to leave the defaults: acrobat and 1. Set all attributes to 0 (it can't have any willpower, intellect or luck, after all), but be generous in the hit points department, give it 2500 points. The color of blood should be white (Skeleton(white)), to simulate dust rising from a blow. Don't touch skills, it won't be using them anyway. Go to AI properties. Make sure that values of Flight, Flee, Alarm, Hello and distance were all 0, and there are no flags in Service tab, or, God forbid, the mannequin will start trading. The new character is ready to be placed in the game world.

5. To regulate its behavior use the following script (from the Japanese House mod):

begin scr_archer_dummy

short nolore
skipanim

if (menumode == 1)
return
endif

if (OnActivate == 1)
return
endif

stopcombat, player

end scr_archer_dummy

It prevents mannequin from speaking with a PC and attacking them.

6. The last step: close the CS, go to ... \Data Files\Meshes\f folder and delete file furn_practice_dummy.nif. Since it mirrored the standard location of the original file in bsa-archive, Morrowind will easily load it from there and you won't need to add this model in archive with your plugin.

A piece of advice: place the mannequin somewhere far away from other NPCs. They will think your training is an assault and will sound the alarm. Also don't attack the dummy near your companion, else they will be locked in battle with it.

Training dummy is actually a very original touch and any mod may benefit from it.

As an addendum, here is the training dummy script by zOmb, which shows how strong the blow was:

Begin TrainingDummy

float hit
float health
float lasthealth
short nolore

addspell 1robotparwlize
OnActivate
set health to GetHealth

if ( health < 1000 )
        if ( health == lasthealth )
                set hit to ( 1000 - health )
                Messagebox "The strength of the blow was %.0f" hit
                sethealth 1000
                set lasthealth to 1000
        else
                set lasthealth to health
        endif
endif
stopCombat

End TrainingDummy

1robotparwlize is an constant paralysis ability.

If there's something missing here, or if something shows up there...[edit]

This script, attached to a container, will detect whether some object has been removed from it:

begin aa_L_int

short once 

if ( menumode )
return
endif

if ( once == 0 )
if ( GetitemCount "object ID" == 0 )
MessageBox "Hmm, the artifact was stolen."
set once to 1
endif
endif

end

And this script displays a message if an object suddenly appears in a container:

begin aa_L_int2

short once 

if ( menumode )
return
endif

if ( once == 0 )
if ( GetitemCount "object ID" > 0 )
MessageBox "The artifact was returned. What is the meaning of this?"
set once to 1
endif
endif

end

Both scripts occur once. Instead of MessageBox you can add a different command, for instance, add a journal note or an NPC guard, or even some scary sound effect.

The phoenix effect from Warcraft III[edit]

In Warcraft III: Frozen Throne the charismatic leader of blood mages has the "phoenix" ability. When it is used, a companion bird appears. This phoenix has a lot of health points, but they immediately start to decrease, until they run out completely, after which the phoenix turns to an egg, and some moments later HP are recovered again. You can do something like this with a PC, using this global script. I made it based on the Kagrenac tools script, which mortally struck the Nerevarine.

begin aa_dae_curse

short extraDamage
float timer

if ( menumode )
return
endif

; if ( getjournalindex "choose which" >= 1 )
; or if ( player->GetItemCount "certain item" >= 1 ), or some other stopper, some other global variable, for example: 
; stopscript "aa_dae_curse" 
; return
; endif


if ( Player->GetHealth <= 15 )
player->ModCurrentHealth 500 
endif

if ( timer < 1 )
set timer to ( timer + GetSecondsPassed )
return
endif

set timer to 0
Set extraDamage to Random 10
Set extraDamage to ( 0 - extraDamage )
Set extraDamage to ( extraDamage - 5 )
player->ModCurrentHealth extraDamage

endif
endif
endif


End

Just after this script is launched, a character's hit points start to decrease, until hitting a threshold of 15 points. After this they will suddenly and dramatically increase (by 500 points), but then go down again. Neither sleep, nor wait can remove this effect; and while restoration spells and potions recover HP, they only lengthen every period. A perfect curse, isn't it? The curse may act as a weird blessing, if the character is not high enough level and their HP are lower than 500.

To put it to an end, the script must be stopped. At the beginning I have offered a few options of doing this (after a journal note appears or after a certain item is received. You can even make it dependent on a time of the day (global variable GameHour) and make the curse only effective at night – but the script will have to be launched again by day. You can stop the script using command stopscript "aa_dae_curse" in the dialogue, or another script.

The similar script can also be used with an NPC.

Gradual disappearing[edit]

This very beautiful special effect can be used in the scene when an actor disappears as a result of a dialogue condition. A common disable, which makes an NPC or a creature disappear can sometimes be too sudden and even irritating. Here is a simple way to make it smoother.

After the dialogue a character becomes partly invisible, and then gradually disappear, as if dissolving.

1. Go to Spellmaking tab and create a new spell, aa_full_illusion, with the invisibility effect. You can also use chameleon. Use any settings, but the spell has to be an ability and the box always succeeds should be ticked. Too high value of magnitude of chameleon effect (e.g. 100) may prevent a player to see an actor under certain lighting conditions.

2. A new journal entry is necessary (in this example "new" with index 1) with contents like: "I spoke with a ghost of a mad daedroth. It told me new facts about its mysterious murder, and then just dissolved into the air."

3. Attach this script to a character that should disappear:

begin hla_az

float timer

if ( Menumode == 1 )
return
endif


if ( journal "new" >= 1 )
Set timer to ( timer + GetSecondsPassed )
endif
if timer > 5
disable
endif

if ( GetDisabled == 1 )
setdelete 1 
return
endif

end

4. Go to dialogue and create a dialogue for the necessary character. Write in the results of the last phrase after which disappearing takes place:

addspell "aa_full_illusion"

journal "new" 1

Note: you can use different value for the timer.

(From comments: you can make disappearing even more smooth by making several chameleon spells with magnitudes 20/40/60/80/100 (for example) and give it to an NPC in order, and then disable it. It's not too complicated, but looks much smoother. Another option is to make 5 similar (just with different IDs) chameleon spells 20p each, and have every one of them play half a second after the previous one.)

A fragment of a key is stuck in the lock[edit]

Using this script you can create situations where various manipulations with objects are needed, much like in Resident Evil game.

In my example a heavy, massive door can't be opened because there is a fragment of the key stuck in the lock. Magic is useless here – indeed, what can you do? Melt this fragment with a fireball? But you will destroy the lock too. Still, you need to get past this door. Thankfully, you have a pair of tongs, which will automatically remove the fragment, and the door can be used as usual.

On technical side of things, we won't make any special fragment, neither shall we animate a scene in which a character tampers with the door. We will only use this script, attached to the door:

begin Tel_door

; made by LofZ

if ( MenuMode == 1 )
return 
endif 

if (GetJournalIndex "aaa_tel" >= 10 )
return
endif

if ( OnActivate == 1 )

if ( player->GetItemCount "repair_prongs" == 0 )
MessageBox "There is a fragment of a key stuck in the lock. Somebody was in a great hurry closing the door, or maybe even tried to break it.", "Done"
return
endif
MessageBox "You have succeeded in removing the fragment."
journal "aaa_tel" 10 
activate
endif

end Tel_door

The journal note "aaa_tel" with index 10 is used as a stop here. You will need to use a similar note or declare local variable of the short type in the beginning and go from there.

Not everyone can be saved (sudden death of an NPC)[edit]

This script makes it so that when a player character returns to an NPC or an animal they talked to before discovers only its dead body. The death is triggered by a journal index.

It is up to you to choose an appropriate situation and figure out what could kill the poor thing – an attempt on its life which PC couldn't prevent, an accident in an egg mine, failure to cure a disease etc. But technically it is not difficult:

1. Create a victim – an NPC or an animal (aa_victim).

2. Write a new journal note 1a_vd and a phrase for index 1, which will say about the tragic outcome of a quest for an NPC. Example: "I have learned that Cammona Tong is going to kill John", "Somebody said that they gave the concoction made by that strange old man to qwama queen. I don't trust him, and should go to the egg mine to check the queen."

3. Use the following script on the victim:

begin VictimScript

; made by lofZ

if ( MenuMode == 1)
return
endif

if ( GetDeadCount "aa_victim" > 0 )
return
endif

if ( GetJournalIndex "1a_vd" < 1 )
return
endif

if ( GetJournalIndex "1a_vd" >= 1 )
Sethealth 0 
return
endif

end

Now, when a note "1a_vd" with index 1 appears in the journal, the poor NPC or the animal will turn into a cold, dead body...

Here is another version of the script, submitted in the comments:

Begin VictimScript
         
short DoOnce
 
if ( MenuMode == 1 )
return
elseif ( doOnce == 1 )
return
endif

if ( GeJournalIndex 1a_vd >= 1 )
sethealth 0
set doOnce to 1
return
endif

END

Script with disable\enable[edit]

Some book (or creature/NPC/any item) suddenly appears after a certain event. This is reflected in the journal.

Useful for:

  • Creating an element of surprise or novelty: "suddenly a Nerenarine's uncle arrives from the capital".
  • If you don't want a PC to find a certain item or to kill an NPC prematurely.

The procedure:

1. Create the item or an NPC that you need and place it in the game world.

2. Write a new journal note, after which the object should appear, if needed.

3. Attach the following script to it. The essence of the script is to make an object inactive or invisible for the character:

begin awake-book

; the script is about a book which suddenly appears in a house when the Nerevarine starts to meet Dagoth Ur in their dreams.
; made by LofZ, sefy.narod.ru

short once 

if ( MenuMode == 1 )
return
endif

if ( once == 1 )
return
endif

if (GetJournalIndex "A1_Dreams" < 1 )
disable
; Note: journal notes is just one of several possible conditions. You can also use, for example:
; if ( player -> gethealth < 50 ) – if PC's health is less than 50 hp
; if ( GameHour >= 0 ), if ( GameHour < 6 ) – if it's nighttime, from 12 p.m. to 6 a. m. 
; don't forget that every if block should be closed with endif. 

endif

if ( once == 0 )
if ( GetJournalIndex "A1_Dreams" >= 1 )
enable
set once to 1

; since now (once == 1) the script stops in the beginning, and the object remains enabled. 
endif
endif

end

Variants of this script for certain applications, submitted by TJ:

1. The most simple example, when an object is disabled by default, but should appear at certain time:

begin AppearScript

short once

if ( once == 0 )
        set once to 1
        disable
elseif ( once == 1 )
        if ( getjournalindex "1a_MyQuest" == 15 )
                enable
                set once to 2
        endif
endif

end

2. When an object exists by default, but should disappear at certain time. This is especially useful for NPCs who should "leave" the location after the completion of a quest. In this script an object will disappear only when PC will return to the cell next time.

begin DissappearScript

short once

if ( once == 0 )
        if ( getjournalindex "1a_MyQuest" >= 31 )
                if ( CellChanged == 1 )
                        disable
                        set once to 1
                endif
        endif
endif

end

3. Script for the objects which are present at day, but not at night. If for your needs the nighttime lasts from 0 to 6 hours, the script will be simpler.

begin day_and_night

short daytime

if ( gamehour < 22.00 ); the time is measured from 0 to 23 hours, keep this in mind to correctly define day from night.
        if ( gamehour > 6.00 ) 
                set daytime to 1; day
        else
                set daytime to 0;  night
        endif
else
        set daytime to 0;  night

endif

if ( daytime == 0 )
        if ( getdisabled == 0 ); so that disable was executed only once, and not every frame
                disable
        endif
elseif ( daytime == 1 )
        if ( getdisabled == 1 ); so that enable was executed only once, and not every frame
                enable
        endif
endif

end

Another variant for disable/enable script:

Begin SCRIPTNAME

if ( GEtJournalIndex ... )
if ( GetDisabled == 0 )
disable
endif
elseif ( GetJournalIndex ... )
if ( GetDisabled == 1 )
enable
endif
endif

END

Turn an NPC to a vampire[edit]

If you want to create a vampire NPC, you will find that the CS doesn't have this race, class or options to turn a character to a creature of the night with just a couple of clicks.

There are 3 scripts in the game (just one in the essence) for the creation of vampire NPC: Vampire_Aundae, Vampire_Berne, and Vampire_Quarra. These scripts set a vampire face and other relevant things. They have one drawback, however – they are too bulky, occupying 88 lines, or almost 2 pages in a .doc file. They are related with vampire quests of Morrowind, and modify NPCs' disposition, if a PC is a member of one of the clans.

It works very well for the Morrowind itself, but for a mod it's just too much unnecessary information. If you are making a plugin about vampires, especially if it features vampires which are friendly towards a character, the standard script can create confusion.

Here is a variant of simplified standard script:

begin L-SimpleVampire

short done

short nolore
short nohello
short noflee
short noidle
short nointruder
short nothief



if ( OnDeath == 1 )
AddItem "ingred_vampire_dust_01" 1
endif


if ( done == 0 )
AddSpell, "Vampire Blood Aundae" 
AddSpell, "Vampire Attributes"
AddSpell, "Vampire Skills"
AddSpell, "Vampire Immunities"
AddSpell, "Vampire Sun Damage"
AddSpell, "Vampire Touch"
AddSpell, "Vampire Aundae Specials"
ModRestoration 75
set done to 1
endif

end

All the aforementioned spells (the lines with AddSpell) should be present, otherwise a character's face wouldn't be vampiric. If you want, you can insert spells of your clan instead of Aundae clan's ones, "Vampire Blood Aundae" and "Vampire Aundae Specials".

These lines are enough for an NPC to become a vampire. You can add more of them to regulate its behavior during a quest.

Notes:

This vampire is not aggressive towards a PC; if you want to change that, go to NPC properties, click AI, and set Fight to 90 or higher.

If you attach the script to an NPC, they will still have standard face in the CS, but in game they will look like a vampire.

Their shouts "attack" and "hit" will be just like those of any usual NPC.

Moving NPCs between cells[edit]

"Moving" an NPC to other cell is usually achieved by creating two different characters, with local scripts enabling one and disabling another when necessary. But sometimes it's better to use only one NPC and actually move them. One can do this with a global script.

For example, here you can see the script for Mehra Milo, which transports her from the Ministry of Truth to the monastery:

begin MoveMehra

if ( GetJournalIndex, "A2_4_MiloGone" == 20 )
if ( cellChanged == 1 )
"Mehra Milo"->PositionCell 1207, 372, -592, 0 "Holamayan Monastery"
StopScript MoveMehra
endif
endif

end

Remember, this script moves an existing NPC, so if they were not placed in the game world to begin with, an error will occur. You wouldn't even be able to load the game before you fix this in the CS.

You can use different journal index, or even do without it. Insert your character's ID and the coordinates of the cell they are to be transported. Other commands may be added as well.

Launch a new global script via the dialogue, or by other means.

Based on Mehra's script I made my own interesting variation. A mercenary by the name of Mer (aa_dj_mer2) is moved to Mournhold sewers, losing his Indoril helmet. The journal gets updated.

begin aa_dj_DarMoveMerv
; Mer is being moved to the sewers
if ( GetJournalIndex, "1a_dj_love" == 20 )
if ( cellChanged == 1 )
"aa_dj_mer2"->PositionCell -540, 2340, -585 0 "Old Mournhold: Bazaar Sewers"
"aa_dj_mer2"->removeitem "Indoril_MH_Guard_helmet" 1
journal "1a_dj_love" 25 
StopScript "aa_dj_DarMoveMerv"
endif
endif

end

Companion teleportation script[edit]

This script teleports a companion to the place where a PC is standing, if there is large enough distance between them. No more headache finding your followers when they get stuck in the scenery!

The idea is not mine – I saw it in one western plugin, but couldn't find out who was the original author. What I am suggesting here is the simplified variant with new way of introducing values of local variable (through the dialogue).

Begin aaa_NewCompanionScript 

Short once
float myx
float myy
float myz
float timer

if ( once == 1 )
if ( GetDistance Player > 750 )
    set timer to timer + GetSecondsPassed
           if ( timer > 15 )
              set timer to 0
         set myx to ( Player->GetPos x )
       set myy to ( Player->GetPos y )
      set myz to ( Player->GetPos z )
     SetPos x myx
    SetPos y myy
  SetPos z myz
return
    endif
  endif
endif

end

The distance and the time here can be changed.

You can activate the script via the dialogue. You will need special phrases anyway, for a companion or an NPC who needs to be escorted.

When your actor is ready to follow a PC, make them say something like: "I am ready to follow you to Vivec", and in results write:

Aifollow, player 0 0 0 0

Set once to 1

And a journal note, if necessary.

Now whenever your character goes far enough from the NPC, the latter will appear just behind your back 15 seconds later. Travelling becomes so much easier and more pleasant! To stop this when the NPC is transported to their destination, or when you want a follower to wait, write a phrase like: "I will stop here, dear Nerevarine" with appropriate conditions, and in results write:

AiWander 0 0 0 60 30 10 0 0 0 0 0 0

Set once to -1

The specialty of this script is that it can be resumed. You only need to write these commands in the dialogue or script:

Aifollow, player 0 0 0 0

Set once to 1

...and stop the script when it is no longer needed.

This way a companion can teleport when following or stay put when waiting.

Be careful with levitation when you are traveling together. If you walk too far away and rise too high, they will teleport to you, only to be smashed against the ground. If you need them to levitate, use the script from the following section.

Companion teleportation and levitation script[edit]

This is a variation of the script above, which enables a companion to levitate together with a PC.

A levitation spell should be original. Moreover, its type should be "ability", so that it isn't dependent on time. In my example, ID of the new spell is "aa_V_MiraSpell" (from the script of girl called Mira, from our plugin "The Grand Dream").

Use this script on your companion ("aa_Companion"):

Begin aaa_NewScript
float myz
float myy
float myx 
float timer
short Once

if ( Once == 1 )
if ( GetDistance Player > 700 )
    set timer to timer + GetSecondsPassed
           if ( timer > 10 )
set Once to 2
endif
endif
endif
if ( Once == 2 )
              set timer to 0
         set myx to ( Player->GetPos x )
       set myy to ( Player->GetPos y )
      set myz to ( Player->GetPos z )
     SetPos x  myx
    SetPos y   myy
  SetPos z  myz
set Once to 1
return
endif
if ( Player->GetEffect, sEffectLevitate == 1 )
   "aa_Companion"->AddSpell "aa_V_MiraSpell"
else
      "aa_Companion"->RemoveSpell "aa_V_MiraSpell"
endif
endif

end

To use this script, write these commands in the dialogue results:

Aifollow, player 0 0 0 0

Set Once to 1, so that the NPC would start to follow a character.

The script will be stopped with a phrase containing this in its results:

AiWander 0 0 0 60 30 10 0 0 0 0 0 0

Set Once to -1

I have to say that followers aren't very good at levitating. The AI is unable to perform descending and ascending as good as a PC. But the script will make moving between Telvanni towers with a companion much easier.