Jump to content

Papyrus Scripting Tutorial Series


Recommended Posts

I wasn't trying to sound bored :sad:. I will try to make future videos less dry/boring, although I tend to be boring vocally. I do have to say trying to teach the basics of variables/events/functions conceptually can be a little dry also (was pretty dry during my intro comp sci classes in my undergraduate software engineering program, which is where I got the delivery style inspiration). Hopefully once I get past the events/functions/objects it will also be more interesting.

Either way, I told my students to have a look over at the Arcane University. They found it helpful, so :thumbsup: .

 

Keep going and update this thread when you do so I can relink it for 'em.

Link to comment
Share on other sites

Ya I always find the hardest part about teaching anything is trying to make it more engaging and programming math etc it is a bit harder. Tie programming basics and property's AND math, gg lol.

Like I said though, I and others with some fortitude and who have already got their feet wet so to speak will be fine with them. But seriously, get hammered and do one. Might be epic you never know :)

Link to comment
Share on other sites

As someone who needs to teach this on a daily basis, layer the content. Some "rules of thumbs"

never introduce any concept in a complex environment

to start, complex projects should be solvable only from the content you have gone over.

If it was me I would Mask the first couple of projects as a "tutorial level" so to speak that will allow you some leniency in the first steps, but do not rely on that for long.

 

After they get a basic understanding then move on to problem solving with code, where you reinforce their ability to think/problem solve for themselves rather than follow step by step instructions.

--For this I try to make projects as open ended as possible, leaving room for their creativity since that will end up being the biggest element in keeping them engaged.

 

Keeping that in mind I then provide my own example and provide it as an "answer sheet/backup plan", which others could ground themselves with just in case their own ideas do not work or they are still confused

 

I think of it like this, imagine you need to get your users from point a to point b, point a is at 0,0 and point b is at 100,100. Rather than have an easy slope for them to trot up to, create a series of plateaus, each plateau focused on a different element of papyrus that you want to teach, once they can overcome this plateau then reward them while simultaneously leading them to the next plateau.

 

The most important aspect of this though, is to reinforce your willingness to teach them. many people will not get this no matter how well of a tutorial you create, having good "customer support" to be concise in a forum-like setting will do much more and be a better use of your time then trying to cover absolutely everything through a pdf

 

 

as for the "Bueller" syndrome (I have it as well so I can relate).

The best thing I can suggest is to not make your videos as the center of your medium but as supplements.

Write out what you want to say, what your projects are, but then make the "customer support" portion as youtube videos with screen capture software. So it will shift from a few 30-40 min videos to many 5-10 min videos.

Even more important is that after doing a few of these 5-10 min videos you will be able to learn how to "lecture" which would allow for more lengthily videos in the future

Link to comment
Share on other sites

Just started on the events/functions series based on the feedback here. I decided to have the presentation portion shorter with more live coding/live testing per ThreeTen's feedback and hopefully it helps incorporate some of Darren's feedback (did not get hammered for the first sorry xD). Once it finishes uploading, here is the first episode of the events/functions (will wait to post future episodes in the events/functions till I have more):

Link to comment
Share on other sites

  • 2 weeks later...

Just posting an update to this post. I am still recording these, currently in the Function Recursion section (Surprised the Creation Kit wiki didn't have information on recursion in brief) which is taking some time to go over in depth.

 

Going to post the video playlist here for people to look at:

 

Also going to copy-pasta some of the recursive math functions here if anyone wanted to play around with them (the last two are from an unrecorded video about helper functions, with a recursion focus on that):

 

Factorial (starting from highest to lowest):

 

 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Input: The base value or subsequent values
;
;The purpose of this function is to recreate the mathematical formula for Factorial
;Example: 4! = 4*3*2*1*1
;Base Case: n = 0 Return 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Int Function OurFactorial(int Num)
	;Our base case - Num = 0
	if (Num == 0)
		return 1
	;Every other case perform the Num * Factorial of previous number	
	Else
		return (Num*OurFactorial(Num - 1))
	EndIf	
EndFunction

 

 

 

Fibonacci sequence (brute force - is recalculation prone and bloats for larger values due to that):

 

 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Input: The base value or subsequent values
;
;The purpose of this function is to recreate the mathematical sequence of Fibonacci
;Example: Fib(2) = Fib(1) + Fib(0) = 1  |  Fib(3) = Fib(2) + Fib(1) = Fib(1) + Fib(0) + Fib(1) = 2
;Base Case: n = 1 return 1 | n = 0 return 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Int Function OurFibonacci(int Num)
	;First base case - Num = 0
	if (Num < 1)
		return 0
	;Second base case - Num = 1
	ElseIf(Num == 1)
		return 1
	;All other cases - Fib(Num - 2) + Fib(Num - 1)	
	Else
		return (OurFibonacci(Num - 2) + OurFibonacci(Num - 1))
	EndIf	
EndFunction

 

 

 

Integer Multiplication by Repetitive Addition:

 

 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Input: First number to add | Second number to keep track of number of times to add
;
;The purpose of this function is to recreate Multiplication via Addition
;Example: 5*5 = 5+5+5+5+5
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Int Function MultiplyByAdd(Int NumToAdd, Int NumTimesToAdd)
	;Base case if NumTimesToAdd is 0
	if (NumTimesToAdd < 2)
		return NumToAdd
	;Every other case
	Else
		return (NumToAdd + MultiplyByAdd(NumToAdd, (NumTimesToAdd - 1)))
	EndIf	
EndFunction

 

 

 

Integer Division by Repetitive Subtraction:

 

 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Input: First number to subtract | Second number to subtract
;
;The purpose of this function is to recreate Integer Division via Subtract
;Example: 20/4 will subtract 5 times
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Int Function DivideBySubtract(Int Num, Int DivideBy)
	;Base Case #1 - If DivideBy is 0
	if (DivideBy == 0)
		return 0
	;Base Case #2 - If Num-DivideBy is 0
	ElseIf ((Num - DivideBy) == 0)
		return 1
	;Base Case #3 - If Num < Divide by
	ElseIf (Num < DivideBy)
		return 0
	;All other valid cases
	Else	
		return (1 + DivideBySubtract((Num - DivideBy),DivideBy))
	EndIf	
EndFunction

 

 

 

Factorial Reverse (starting from 0 and working to desired value):

 

 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Inputs: Base Value | Desired Factorial
;
;The purpose of this function is to calculate Factorial in reverse
;Example: Fact(3) = 1*1*2*3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Int Function FactorialReverse(Int BaseValue, Int DesiredValue)
	;Base Case - If Base Value is equal to Desired Value
	if (BaseValue == DesiredValue)
		;For BaseValue of 0
		if (BaseValue < 1)
			return 1
		;All other BaseValues	
		Else
			return BaseValue
		EndIf
	;All other cases	
	Else
		;For BaseValue of 0
		if (BaseValue < 1)
			return (1 * FactorialReverse((BaseValue + 1),DesiredValue))
		;All other cases
		Else
			return (BaseValue * FactorialReverse((BaseValue + 1), DesiredValue))
		EndIf
	EndIf	
EndFunction

 

 

 

Float Division by Repetitive Subtraction - Currently to Hundredths Place Precision:

 

 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Inputs: The first number to subtract | the second number to subtract
;
;The purpose of this function is to recreate floating point division by subtracting
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Float Function FloatDivBySubtract(Float Num, Float DivideBy)
	;Base Case #1 - If Divided by is 0
	if (DivideBy == 0.0)
		return 0.0
	;Base Case #2 - If Num-DividedBy is 0
	ElseIf ((Num - DivideBy) == 0.0)
		return 1.0
	;Base Case #3 - If Num < DividedBy && Num is not 0
	ElseIf ((Num < DivideBy) && (Num  > 0.0))
		return (0.0 + FloatDivBySubtractTens(MultByTen(Num), DivideBy))
	;All other valid cases
	Else
		return (1.0 + FloatDivBySubtract((Num - DivideBy), DivideBy))
	EndIf	
EndFunction

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Inputs: The first number to subtract | The second number to subtract
;
;The purpose of this function is to assist in FloatDiv for the tenths place
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Float Function FloatDivBySubtractTens(Float Num, Float DivideBy)
	;Base Case #1 - If Divided by is 0
	if (DivideBy == 0.0)
		return 0.0
	;Base Case #2 - If Num-DividedBy is 0
	ElseIf ((Num - DivideBy) == 0.0)
		return 0.1
	;Base Case #3 - If Num < DividedBy && Num is not 0
	ElseIf ((Num < DivideBy) && (Num  > 0.0))
		return (0.0 + FloatDivBySubtractHundredths(MultByTen(Num), DivideBy))
	;All other valid cases
	Else
		return (0.1 + FloatDivBySubtractTens((Num - DivideBy), DivideBy))
	EndIf	
EndFunction

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Inputs: The first number to subtract | the second number to subtract
;
;The purpose of this function is to assist in FloatDiv for the hundredths place
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Float Function FloatDivBySubtractHundredths(Float Num, Float DivideBy)
	;Base Case #1 - If Divided by is 0
	if (DivideBy == 0.0)
		return 0.0
	;Base Case #2 - If Num-DividedBy is 0
	ElseIf ((Num - DivideBy) == 0.0)
		return 0.01
	;Base Case #3 - If Num < DividedBy && Num is not 0
	;Terminate decimal calculation...only have two points of FP precision
	ElseIf ((Num < DivideBy) && (Num  > 0.0))
		return 0.0
	;All other valid cases
	Else
		return (0.01 + FloatDivBySubtractHundredths((Num - DivideBy), DivideBy))
	EndIf	
EndFunction

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Inputs: Float To Multiply
;
;The purpose of this function is to multiply a float value 10 times
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Float Function MultByTen(Float Num)
	return (Num + MultByTenHelper(Num , 9))
EndFunction

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Inputs: Float to Multiply | times to multiply
;
;The purpose of this function is to assist MultByTen
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Float Function MultByTenHelper(Float Num, Int TimesMult)
	;Base Case - if TimesMult is 1
	if (TimesMult < 2)
		return Num
	;All other cases	
	Else
		return (Num + MultByTenHelper(Num, (TimesMult - 1)))
	EndIf	
EndFunction

 

 

 

Float Multiplication by Repetitive Addition - Uses Division for the decimals (Only way I could think of for decimal precision) [requires the previous code]:

 

 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Inputs: Float to Multiply | Other Float to Multiply
;
;The purpose of this function is to perform multiplication through addition.  Decimal portion of the answer might require use of the division functionality
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Float Function FloatMultByAddition(Float NumToAdd, Float NumTimesToAdd)
	;Base Case - NumTimesToAdd is 0
	if (NumTimesToAdd == 0.0)
		return NumToAdd
	;Base Case #2 - NumTimesToAdd is less than 1 but greater than 0
	ElseIf ((NumTimesToAdd < 1.0) && (NumTimesToAdd > 0.0))
		return (0.0 + FloatDivBySubtractTens(NumToAdd, MultByTen(NumTimesToAdd)))
	;All other cases
	Else
		return (NumToAdd + FloatMultByAddition(NumToAdd, (NumTimesToAdd - 1.0)))
	EndIf	
EndFunction

 

 

Link to comment
Share on other sites

Good examples of small functions, but I'd suggest keeping the examples limited to things you might typically do in Papyrus and complicated math is really not something Papyrus was designed for or is particularly efficient at.

 

For example, this function might be a good way to showcase how an object, array, and a loop can be used to keep track of actors for some purpose:

 

 

; Adds the actor to the next empty (None) position in the actor array.

; Returns true if the actor was added or was already present in the array.

; Returns false if there was no room left in the array to add the actor.

bool Function AddActorToArray(Actor actorRef, Actor[] actorArray) global

int i = 0

 

while i < actorArray.Length ; Find the next available position.

 

if actorArray == actorRef ; Actor is already in the array.

return true

 

elseIf actorArray == None ; Actor is added to the empty position.

actorArray = actorRef

return true

 

else ; Continue iteration.

i += 1

endIf

endWhile

 

return false ; No room in the array.

EndFunction

 

 

*Sigh* If only Papyrus supported generic types, then you wouldn't have to rewrite that function for every single object type.

Link to comment
Share on other sites

While I agree there needs to be everyday applications such as the array example you provide (going over Arrays after I finish up the Recursion segment), I believe math functions are also important. I have been spending a lot of time looking up common math functions (ln, log, combinations, factorial, fibonacci, multiplication/division via addition/subtraction, determining even/odd, etc.) and find that the majority of those functions can be done given the operations Papyrus gives us. With little documentation on utilizing these math functions within Papyrus, I think it is beneficial to expand our math tools there, and using the tutorials as an avenue for expanding the math tools seemed like the natural course of action. A secondary result of the Events/Functions segment will be a math library.

 

I have been utilizing other examples that are not math related when the time permits in the episode (did a recursive concatenation function in the Helper Functions video, where the user provides a message and a MessageBox pops up with the message displayed n+1 times. Example RecConcat("Yo ", 5) displays Yo 6 times). Once there are more tools built up from the episodes, I will be going into practical examples such as profit calculators from player-owned mines, Message Box mini-games such as Tic-Tac Toe, or a reward system based on junk items (i.e. rewarding scrolls/books for a certain amount of burned books/ruined books turned in).

 

I do agree that generic type support would have been helpful.

Link to comment
Share on other sites

  • 1 month later...

Just posting an update saying this is not dead. I got busy for a bit (and have been in a funk...but not important) and just started recording more videos. Functional Recursion is finished and I have started on the Arrays sub-section, and finished Functions with Array Parameters (it isn't uploaded yet [assembling the 7 video files for the episode into a single file], but it will get there). Sorry for the delay in episode generation.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...