Pages: [1] |
| |
Author |
Topic: Companion 1.3 in-depth (for the technically
inclined)... (Read 732 times) |
Grumpy
|
I put this up
over at TheLys' site some time ago and it kind of got
lost.
Emma asked me to put it up
here.
This is a variation of the original warping
I and Devlor with great assistance from Reznod developed
over two years ago (from the 1.3 companion mod).
This is just intended as kind of a tutorial for
those who are intrested in scripting. Lot of
things you can do in script. This is just one
facet of the thing.
This is the simple version
used for standard companion "enhanced"
following:
-------------------------------------------------------------------------------------
float myx float myy float myz float
timer
if ( GetCurrentAIPackage == 3 ) if (
GetWeaponDrawn == 1 ) return elseif (
GetDistance Player > 800 ) set timer to timer +
GetSecondsPassed if ( timer > 8 ) 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 endif endif endif endif
-------------------------------------------------------------------------------------
Line for line explanation:
if (
GetCurrentAIPackage == 3 )
This line tells the
game engine that this companion has to be in follow mode
before the rest of the script processes. You don't want
to tell them to wait somewhere just to see them start
warping behind you once you walk away from them.
Basically, you want them to be in AIFollow mode, and
ONLY in AIFollow mode for the warping to work.
if ( GetWeaponDrawn == 1 )
This function
defines whether the object that it's attached to
(companion in this instance) has their weapon out or
not.
"GetWeaponDrawn" is a boolean function,
meaning it is either true or false (1=true 0=false). A
script (unless defined differently) runs once every
frame of the game, and the checks that you use in the
script are in-turn made once every frame, so (for
example), this script runs at the beginning of the frame
(script runs from top to bottom), and the first "check"
encountered is (after CurrentAIPackage)
"GetWeaponDrawn". If the check returns "1" here, then
the next line is processed...
Next line, and
subsequently the rest of the script are dependent on
this first "check".
return
This line
stops further script processing. None of the rest of
this script will be processed as long as the
"GetWeaponDrawn" function returns true. Reason we do
this is to keep a companion from warping while in
combat. They only draw their weapons when in combat, so
we can assume that if their weapon IS drawn, that combat
is occuring.
Side note: When friend Devlor
suggested this as an appropriate qualifier to keep
companions from warping during combat, we thought we had
it whipped at that point. However, there is a game bug
that happens on occasion, and they fail to sheathe after
combat is over. This presents a problem because as long
as they have their weapons drawn, none of the rest of
the script processes, and warping is effectively
"broken" at that point. Generally why you'll see some
kind of mechanisim used in dialog to force a sheathe.
Always bear in mind when scripting that not all
is black and white. Other factors can and do interfere
sometimes.
elseif ( GetDistance Player > 800
)
If first condition exists (GetWeaponDrawn ==
1), do this. elseif first condition does NOT exist we
move to the next check; second condition exists
(GetDistance Player > 800), do this.
Basically, this is the "trip wire" that
activates warping. Companion is too far away. Normal
following parameters as defined by the game engine
itself are between 180gu near distance ("game units", or
the measure of distance used by the game itself (1gu =
.57 virtual inches)), and about 480gu far distance.
Given that you are on flat terrain with no obstacles,
the game engine defines that a companion should always
be within this 180gu to 480gu range.
What we are
doing with this line of code is making an assumption
that if they are beyond this outside distance (480gu),
that they are probably stuck.
Now the reason I
used 800gu here, is that on occasion, the AI works and
they (companions) will figure it out on their own. By
using 800gu, we minimize warping to some degree to make
it more asthetically pleasing. This is, however, a
relatively arbitrary number, and I've seen it set
shorter, so it's pretty much "user taste".
set
timer to timer + GetSecondsPassed if ( timer > 8
) set timer to 0
OK... Companion is STILL
outside of normal parameters (480gu), and is presumed
"stuck" at this point (remember that this script is
processing 30 times per second on a computer that runs
the game at 30fps).
This section actually serves
two purposes. One reason is, again, as the 800gu
distance above, used for reasons of asthetics, and
allows the companion an additional 8 seconds (another
arbitrary number BTW) to get back within normal
following distance without warping. The second is a bit
more complicated, but easy enough to understand if you
consider that "GetWeaponDrawn" acts as a dynamic timer
in the sense that as long as the companion has their
weapon out, none of the rest of the script processes. So
we actually have two different timers working here:
"GetWeaponDrawn" acts as the first, but only during
combat, in that it keeps the companion from warping
during combat. It covers the amount of time from the
onset of combat through the end of combat. Now once
combat is over, if we didn't have a timer running,
companion would instantly warp back to the player. The
"real" timer, and the second purpose of it, is just to
allow them enough time to return to the player without
warping... IF THEY DON'T GET STUCK. If they do get
stuck, and the 8 seconds elapses, then we move to the
next area of the script.
lines defined:
set timer to timer + GetSecondsPassed
-this initiates the timer
if ( timer
> 8 )
-defines the length of time, so if the
timer is greater than (>) 8 seconds...
Remember? If condition exists, do this...
set timer to 0
-resets the timer to 0
for the next go-round
(Script is processing 30
times per second from top to bottom. Defined conditions
HAVE to be met for the script to contine processing.
Distance is now exceeded, and time has run out. The two
conditions we have defined for warping to occur are now
true.)
set myx to ( Player->GetPos x )
-we use our variables here (floats in this case
because these numbers are not simple as in 1.2,3 (short
variables), but coordinates as in -167.312)
-set
variable myx to the player's "x" coordinate
set
myy to ( Player->GetPos y ) set myz to (
Player->GetPos z )
-same with these two,
except that one is for the player's "y" coordinate, and
the other is for the player's "z" coordinate
All
objects in the game are mapped, and have coordinates
that are in relation to the 0,0 coordinate. I'll
probably screw this up, but I think "x" is east/west,
"y" is north/south, and "z" is up/down (height).
SetPos x myx
-we now have the player's
coordinates, so to complete the sequence, we mearly move
the object (our companion) from his/her current location
to the player's location
-set companion's x
position (SetPos x) to myx (myx being the player's
current x coordinate)
SetPos y myy SetPos z
myz
-same with these two, except that one is for
the player's "y" coordinate, and the other is for the
player's "z" coordinate
...and the "endif"
lines to terminate the sequence...
A rub:
What if the player levitates? Obviously without some
kind of qualifier, once the distance is reached, and the
timer times out, the companion will warp. Not good...
A simple qualification (I'm not going to
get into companion levitation abilities here, the
following addition simply keeps them from warping if the
player does levitate, and is one of the simplest fixes):
-------------------------------------------------------------------------------------
float myx float myy float myz float
timer
if ( GetCurrentAIPackage == 3 ) if (
Player->GetEffect sEffectLevitate == 1 ) AIWander
0 0 0 0 endif
if ( GetWeaponDrawn == 1 )
return elseif ( GetDistance Player > 800 )
set timer to timer + GetSecondsPassed if ( timer
> 8 ) 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 endif
endif endif endif
-------------------------------------------------------------------------------------
if ( Player->GetEffect sEffectLevitate == 1 )
AIWander 0 0 0 0 endif
Tells the game
engine that if the player is levitating, then companion
is to stop right where they are. Once the player has
ended the levitation sequence, then he/she will need to
return to the companion and initiate follow mode again.
Remember that this script is running once every
frame. First check is made; if player IS levitating,
AIPackage gets changed to something other than 3 (-1
maybe (not sure)), so the next frame, the script
processes again; the first line is checked, and
AIPackage is NOT 3, so none of the rest of the script
gets processed. No warping.
Critters:
-------------------------------------------------------------------------------------
float myx float myy float myz float
timer
if ( GetCurrentAIPackage == 3 ) if (
Player->GetEffect sEffectLevitate == 1 ) AIWander
0 0 0 0 endif
if ( GetDistance Player >
800 ) set timer to timer + GetSecondsPassed if (
timer > 8 ) 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 endif
endif endif endif
-------------------------------------------------------------------------------------
Rub with a critter is that they don't use
weapons, so we can't use "GetWeponDrawn" here. In this
case, the best that can be done is to just eliminate
that line altogether and just use a timer. |
| | |
Regan
Eternally
Helpful Adventurer
OfflinePosts: 188
|
Well you lost
me just after the first 'float' :? It's
good to have it explained, I think I understand
how it works now, my scripting knowledge is pushed to
its limits making a messagebox pop up when you activate
something. I can see how the basic 'follow' part is so
efficient, being such a short piece of code.
Will you be explaining the more advanced 3.1
script as well? I'm off to adjust my companion's
follow distance and warp delay . . . . . . Thanks
Grumpy |
| | |
Grumpy
|
I have fits
with message boxes myself... :oops: Reason I got away
from them after the Cally/Gabran mods. I'll bet it
took me a month to get that one working (no scripter
me...). Anywho... When me and Emma talked
about putting this up here, she PROMISED that she would
do a short tutorial for the dialog end of this.
(poster makes his get-away...) esbolt
What you would need in dialog to get a companion
to follow/wait/etc... So as soon as she can take
time away from her most busy schedule, we can hope to
see that up here as well. |
| | |
Emma
|
I have fits with message boxes
myself... :oops: Reason I got away from them after the
Cally/Gabran mods. I'll bet it took me a month to
get that one working (no scripter
me...). Anywho... When me and Emma talked
about putting this up here, she PROMISED that she would
do a short tutorial for the dialog end of this.
(poster makes his get-away...) esbolt
What you would need in dialog to get a companion
to follow/wait/etc... So as soon as she can take
time away from her most busy schedule, we can hope to
see that up here as well. Hmmm... this sounds a tad bit
like blackmailing to me cirant Oh yes... I
WILL attend to it... later. Until then, have a
cicheer :hello2: |
| | |
joetheimperial
Balmora Beggar
OfflinePosts: 28
|
That would be a
wonderful read! All that I can ever seem to accomplish
with scripting is to add a topic to a companion, or add
companion share to a slave (great way to make a
speaking, moving model or dancer; rather than just a
maniquin). Dialog scripting is SO much
friendlier. GUIs are our friends! I'll sit
patiently..........keep my whistle wet.............and
await your wise words! |
| | |
FofA
Balmora Beggar
OfflinePosts: 32 |
Reminds me of
my C++ days.
Thanks, that was actually very easy
to read and informative to boot. |
Amanda
> ES forums | | |
edwardsmd
ThankYou Adventurer
OfflinePosts: 379
|
...Dialog scripting is SO much
friendlier. GUIs are our friends!... There must
be something wrong with me then. Scripting seems easy to
follow, Dialog makes my head hurt. :( |
Get
the updated TESCS Manual I put together. Get it at Emma's
site! Available in doc and pdf
flavor! Proud to be a
Roamer! | | |
mercurybard
Balmora Beggar
OfflinePosts: 47
|
Nice
explanation, Grumpy, really easy to
understand. |
| | |
MistyMoon
ThankYou Legend
OfflinePosts: 546
|
Love Grumpy's
comp v3.1 and when i added the AlmDivScript from version
v2.2 it is just to good. :wink: |
Find my latest updates and mod's
atProud member of Elder Scrolls
Central | | |
Emma
|
Quuote from
Grumpy
Anywho... When me and Emma talked
about putting this up here, she PROMISED that she would
do a short tutorial for the dialog end of this.
(poster makes his get-away...) esbolt
What
you would need in dialog to get a companion to
follow/wait/etc...
So as soon as she can take
time away from her most busy schedule, we can hope to
see that up here as well. Better late than
never... although it breaks my heart that you won't be
here to read it (and tease me for my veeeery late
reply...), dearest Grumpy. If you use
Grumpy's Companion project, there is already dialog
included - some greetings, and the basic topics: follow,
combat etc. The most important thing to know when
using the companion project as a base for your
mod: YOU HAVE TO RE-WRITE THE
DIALOG!!!! There's no way around this. You
see. If you just re-filter the existing dialog lines for
your companion, the original companion will lose her
dialog!! Instead, just make one new dialog entry
for each original entry. The text and the name of the
topic can be the same, that doesn't matter. The
important thing is that you make a brandnew dialog line.
And make sure that you copy the text in the
result-boxes! This text is was makes the companion react
in the right way (follow you, stay, change fighting
technique etc). Same goes for the greetings. You
need new greetings for your companion. As for
greetings, never put them at the very top of the
greetings section! If other modders do the same thing
with their mods, it may corrupt things ingame. Instead,
stick your new greetings somewhere in the middle of the
greetings section. If you are making a guard
companion, you will have to put the greetings in section
0, else other guard greetings will override those by you
if you for instance commit a crime. I'll
leave it like this for the moment, feel free to post
questions or comments... |
| | |
Emma
|
Adding new
topicsIf you want to add a new topic for
your companion, there are several ways to do
it. In some of Grumpy's templates, there is an
addtopic function in the script, and if you haven't
started to use your companion yet, you can just add your
topic there: addtopic "my topic" If the
script isn't prepared for AddTopic, or if you are
already using the companion, the easiest way to do
this is to put a command in a dialog result box (the
block below where the actual dialog is) Put it for
instance int the topic -follow, approx like
this:
Text in text-block: Do you want me
to follow you, %PCName?
Text in resultbox below
text-block:
AddTopic "my topic"
<--this line is obviously
what you add choice "Yes, come with me" 1 "No, stay"
2 Please note that you naturally have to
USE this topic in order to add the new
topic! Please note that a topic that doesn't
beging with - or * or any of the other things companion
mods often use, will be hyperlinked and added
automatically if someone use the topic in their
dialog |
| | |
Emma
|
How to make
a companion dance
Assing an animation file to
the companion. You do this in the npc-informationbox
that you use to change heads and hairs on your
companion. Right below the heads and hairs option,
you'll fnd a box for animation. The most common dancing
animation is the one by Bethesda, called
anim_dancinggirl.nif . It's located on your
TESCS-harddrive.
RX31 has made some very
interesting dancing animations, too, and they are
available for download at Planet Elder
Scrolls.
------------------------------
Now,
make a new topic for dancing (see previous post here
regarding how to add topics).
In the resultbox
you'll write
When you want companion to
dance: AiWander 0 0 0 0 0 0 0 0 0 0 0 100
When
you want companion to stop dancing and follow
you: AiFollow player 0 0 0 0
When you want
companioin to stop dancing and stand still: AiWander
0 0 0 0
|
| | |
Neko
Eternally
Helpful Commoner
OfflinePosts: 84
Over
there. That's new. |
How to make
a companion cast spells (through a dialogue
choice) Set up the spell you want them to use in
Spellmaking, I typically make my own custom ones for
fear of other mods but it's not necessary, in your
dialogue, write something like:
text: I hate
you!
results: Cast "fireball"
Player Goodbye
the Goodbye is
generally a good idea, they can only do one thing after
you leave the conversation with them and this avoids a
lot of different actions stacking up. If you want them
to cast a spell on themselves, for example, healing
themselves, there's a trick- you always need to give a
target in the Cast function. But Player works
equally well in this case, even if your chosen spell is
"On Self":-
text: I could really use some
healing.. hold on a
moment..
results: Cast "hearth heal"
Player Goodbye
in this case, even though
we need the Player to target, "hearth heal" is an "On
Self" spell, so it works OK and our companion can heal
themself. Note: These spells are manaless and
always suceed. If you want to develop a chance of
failure or a magicka drain + inability to cast if not
enough magicka, you need to implement it yourself.
Useful example functions are
Set mana to ( GetCurrentMagicka
) and
ModCurrentMagicka,
-20 -Neko |
| | |
|
Pages: [1] |
| |
|