Difference between revisions of "User:Fg109"
imported>Fg109 |
imported>Fg109 |
||
Line 1: | Line 1: | ||
I was trying to write a tutorial on papyrus basics on my user page, but I realize I absolutely suck at explaining things. I'm just going to post (parts of) scripts that I made and liked. | I was trying to write a tutorial on papyrus basics on my user page, but I realize I absolutely suck at explaining things. I'm just going to post (parts of) scripts that I made and liked. | ||
== Saving Actor's Outfit == | |||
A function returning a 32 element array containing an actor's equipped (base) items. Requires SKSE. | |||
<source lang="papyrus">Form[] Function SaveOutfit(Actor akActor) | |||
Form[] SavedOutfit = new Form[32] | |||
int slot = 1 | |||
int i | |||
int j | |||
while (i < 32) | |||
Form TempForm = akActor.GetWornForm(slot) | |||
if (TempForm) | |||
SavedOutfit[j] = TempForm | |||
j += 1 | |||
endif | |||
slot *= 2 | |||
i += 1 | |||
endwhile | |||
Return SavedOutfit | |||
EndFunction</source> | |||
There will probably be empty elements, since the actor probably is not wearing an item in every single slot. Automatically sorted so that empty elements are at the end of the array. | |||
== Converting Local/Global Rotation == | == Converting Local/Global Rotation == |
Revision as of 09:49, 1 June 2012
I was trying to write a tutorial on papyrus basics on my user page, but I realize I absolutely suck at explaining things. I'm just going to post (parts of) scripts that I made and liked.
Saving Actor's Outfit
A function returning a 32 element array containing an actor's equipped (base) items. Requires SKSE.
Form[] Function SaveOutfit(Actor akActor)
Form[] SavedOutfit = new Form[32]
int slot = 1
int i
int j
while (i < 32)
Form TempForm = akActor.GetWornForm(slot)
if (TempForm)
SavedOutfit[j] = TempForm
j += 1
endif
slot *= 2
i += 1
endwhile
Return SavedOutfit
EndFunction
There will probably be empty elements, since the actor probably is not wearing an item in every single slot. Automatically sorted so that empty elements are at the end of the array.
Converting Local/Global Rotation
I wrote a function for converting from local to global rotation. I find that I use it a lot.
Float[] Function ConvertRotation(Float AngleX, Float AngleY, Float AngleZ, Bool FromLocal = True)
Float NewX
Float NewY
if (FromLocal)
NewX = AngleX * Math.Cos(AngleZ) + AngleY * Math.Sin(AngleZ)
NewY = AngleY * Math.Cos(AngleZ) - AngleX * Math.Sin(AngleZ)
else
NewX = AngleX * Math.Cos(AngleZ) - AngleY * Math.Sin(AngleZ)
NewY = AngleY * Math.Cos(AngleZ) + AngleX * Math.Sin(AngleZ)
endif
Float[] Angles = new Float[3]
Angles[0] = NewX
Angles[1] = NewY
Angles[2] = AngleZ
Return Angles
EndFunction
Angle Z stays the same, because "Local" in this case means "What are the new X and Y angles if I turn (change the Z angle) to this heading?"
Multi Fire Spell
To create a multi-fire spell, you will need to create these things:
- An activator using the model of one of the magic projectiles
- Another activator that doesn't need any model (just duplicate DummyObject)
- An explosion that spawns the second activator
- A projectile that creates the explosion
- A spell that uses the projectile
The first activator should have a script with an OnTranslationAlmostComplete event that will place an explosion at itself (not the custom one you made) in order to inflict damage, then disable and delete itself.
The second activator should use this script:
Scriptname MissileTargetScript extends ObjectReference
Activator Property MissileObj Auto
ObjectReference[] Missiles
Int Count
Event OnInit()
Actor Player = Game.GetPlayer()
Missiles = New ObjectReference[128]
Count = Utility.RandomInt(3, 13)
Missiles[0] = Player.PlaceAtMe(MissileObj)
Missiles[0].MoveTo(Player, 75 * Math.Sin(Player.GetAngleZ()), 75 * Math.Cos(Player.GetAngleZ()), \
0.75 * Player.GetHeight())
Float OffsetAngle = 360 / (Count - 1)
int index = 1
while (index < Count)
Missiles[index] = Missiles[0].PlaceAtMe(MissileObj)
Float DistanceXY = 64 * Math.Sin(OffsetAngle * (Index - 1))
Float DistanceZ = 64 * Math.Cos(OffsetAngle * (Index - 1))
Missiles[index].MoveTo(Missiles[0], DistanceXY * Math.Sin(Missiles[0].GetAngleZ() - 90), \
DistanceXY * Math.Cos(Missiles[0].GetAngleZ() - 90), DistanceZ)
Missiles[index].SetAngle(0, 0, Missiles[0].GetAngleZ() + Utility.RandomInt(-45, 45))
index += 1
endwhile
Utility.Wait(0.25)
index = 0
while (index < Count)
SmoothCurve(Missiles[index], Self, 1000)
index += 1
endwhile
Disable()
Delete()
EndEvent
Function SmoothCurve(ObjectReference A, ObjectReference B, Float Speed)
Float AngleZ = A.GetHeadingAngle(B)
if (AngleZ < -45)
Float OffsetAngle = -45.0 - AngleZ
AngleZ = -45.0
A.SetAngle(0, 0, A.GetAngleZ() + OffsetAngle)
elseif (AngleZ > 45)
Float OffsetAngle = 45.0 - AngleZ
AngleZ = 45.0
A.SetAngle(0, 0, A.GetAngleZ() + OffsetAngle)
endif
Float DistanceXY = Math.sqrt((B.X - A.X) * (B.X - A.X) + (B.Y - A.Y) * (B.Y - A.Y))
Float SplineMagnitude = DistanceXY / Math.Cos(AngleZ)
Float AngleZEnd = A.GetAngleZ() + (A.GetHeadingAngle(B) * 2)
A.SplineTranslateTo(B.X, B.Y, B.Z, 0, 0, AngleZEnd, Math.Abs(SplineMagnitude) * 0.75, Speed)
EndFunction
So what happens is you cast your custom spell. The custom spell creates a projectile. When the projectile hits something, it causes an explosion. The explosion would spawn an activator (the second one, our 'missile target'). The missile target would create 3 to 13 missiles (the first activators) and place them in a clock-like arrangement in front of the player. Then the missiles will fire themselves at the target (in a random curved trajectory) and explode when they reach it.
Basic Hunger Mod
Give actors an ability with this script:
Scriptname fg109TestMEScript extends ActiveMagicEffect
Faction Property HungerFaction Auto
Int Property UpdateInterval Auto
Formlist Property FoodsHighList Auto
Formlist Property FoodsMidList Auto
Formlist Property FoodsLowList Auto
Keyword Property VendorItemFood Auto
Actor Myself
Event OnEffectStart(Actor akTarget, Actor akCaster)
Myself = akTarget
;if NPC is not in the hunger faction, add him/her in
if (Myself.GetFactionRank(HungerFaction) < 0)
Myself.SetFactionRank(HungerFaction, 0)
endif
;increment "hunger variable" every UpdateInterval seconds
RegisterForUpdate(UpdateInterval)
EndEvent
Event OnUpdate()
if (Myself.GetFactionRank(HungerFaction) < 100)
;increment the "hunger variable" by 1
Myself.ModFactionRank(HungerFaction, 1)
else
;die of hunger
Myself.Kill()
endif
EndEvent
Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
if (FoodsHighList.HasForm(akBaseObject))
;we just ate something from FoodsHighList
Myself.ModFactionRank(HungerFaction, -5)
elseif (FoodsMidList.HasForm(akBaseObject))
;we just ate something from FoodsMidList
Myself.ModFactionRank(HungerFaction, -3)
elseif (FoodsLowList.HasForm(akBaseObject))
;we just ate something from the FoodsLowList
Myself.ModFactionRank(HungerFaction, -1)
elseif (akBaseObject.HasKeyword(VendorItemFood))
;a food not in one of the lists (mod added?)
if (akBaseObject.GetGoldValue() < 3)
Myself.ModFactionRank(HungerFaction, -1)
elseif (akBaseObject.GetGoldValue() < 5)
Myself.ModFactionRank(HungerFaction, -3)
else
Myself.ModFactionRank(HungerFaction, -5)
endif
endif
if (Myself.GetFactionRank(HungerFaction) < 0)
;completely full
Myself.SetFactionRank(HungerFaction, 0)
endif
EndEvent