Rune is a third person action, combat, and adventure games with strong themes from Norse mythology. You play a young Viking trying to uncover the mysteries around recent attacks on your village. The game is played from third person perspective to make the melee combat with a huge variety of weapons more fun, as well as giving you a chance to fully appreciate and explore the complex world.

Post tutorial Report RSS Coding Decorations

Goblin of Truth Tutorial - Ever wanted to know the future? Author: Charles "MrBlonde" Palmer

Posted by on - Basic Client Side Coding

Goblin of Truth Tutorial - Ever wanted to know the future?

In this tutorial we'll cover some very basic program flow and create a new decoration (an object that is a model but acts like part of the level) for level designers to add into thier level. But our's will be different, rather than just a static object we're going to add the ability for Player to run up and use it. In this example we'll create a new Goblin statue that when used generates a message fortelling the future (like those 8-Ball toys).

Firstly create a new package (for instructions see my general coding information tutorial) called GoblinOfTruth. In the classes directory add a new file called GoblinOfTruth.uc and add the following to it.

Someone wrote: //=============================================================================
// GoblinOfTruth - Cheap at twice the price!
//=============================================================================
class GoblinOfTruth extends StatueGoblin;

function name GetUseAnim()
{
return('pumpTrigger');
}

function bool CanBeUsed(Actor Other)
{
return(true);
}

function int GetUsePriority()
{
return(4);
}

function bool UseTrigger(actor Other)
{
local int RandomInt;
local RunePlayer Player;
local string PlayerName;
if(Other.IsA('RunePlayer'))
{
Player = RunePlayer(Other);
PlayerName = Player.PlayerReplicationInfo.PlayerName;
RandomInt = Rand(8);

switch(RandomInt)
{
case 0:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", AYE!");
break;
case 1:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", Are ye jesting?");
break;
case 2:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", That will never be!");
break;
case 3:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", Tis unlikely.");
break;
case 4:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", The mug is cloudy!");
break;
case 5:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", Indeed.");
break;
case 6:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", That will come to pass.");
break;
case 7:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", FEEL LOKI'S WRATH!!!");
break;
default:
break;
}
return(true);
}
}

defaultproperties
{
bDestroyable=False
bStatic=True
bJointsBlock=True
bJointsTouch=True
}

Taking a closer look at the file itself, firstly we define the class GoblinOfTruth, which inherits from StatueGoblin. The complete hierarchy is Object->Actor->Decoration->DecorationRune->Statue->StatueGoblin->GoblinOfTruth.

Someone wrote: //=============================================================================
// GoblinOfTruth - Cheap at twice the price!
//=============================================================================
class GoblinOfTruth extends StatueGoblin;

The next three functions are very simple and pretty self explanatory the first GetUseAnim() returns the animation to play when the Statue is used (in this case we use the switch flicking animation, stroke that Goblin!). Then next CanBeUsed(Actor Other) checks whether Other can use the Statue or not and finally GetUsePrioriy() returns a number which relates to the priority for using the Statue if there are other items present (ie. you don't want to stop people picking up nearby weapons, but you might want to use the Statue before another object).

Someone wrote: function name GetUseAnim()
{
return('pumpTrigger');
}

function bool CanBeUsed(Actor Other)
{
return(true);
}

function int GetUsePriority()
{
return(4);
}

The next function UseTrigger(Actor Other) is the real meat of the class, it gets called everytime our Goblin is stroked (or used to you and me).

Someone wrote: function bool UseTrigger(actor Other)
{
local int RandomInt;
local RunePlayer Player;
local string PlayerName;
if(Other.IsA('RunePlayer'))
{
Player = RunePlayer(Other);
PlayerName = Player.PlayerReplicationInfo.PlayerName;
RandomInt = Rand(8);

switch(RandomInt)
{
case 0:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", AYE!");
break;
case 1:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", Are ye jesting?");
break;
case 2:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", That will never be!");
break;
case 3:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", Tis unlikely.");
break;
case 4:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", The mug is cloudy!");
break;
case 5:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", Indeed.");
break;
case 6:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", That will come to pass.");
break;
case 7:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", FEEL LOKI'S WRATH!!!");
break;
default:
break;
}
return(true);
}
}


First off we define a few variables to hold a random number, details of the Player who used the Statue and the Players name. We then check to make sure that the right type of class is using the Statue, in this case a Player from Rune! We get the Players details and access the PlayerReplicationInfo (a class that holds all the details relating to the Player that other Players might want to know) to get the Players name. Finally we generate a random number between 0 and 7 (thus the number 8).

Someone wrote: function bool UseTrigger(actor Other)
{
local int RandomInt;
local RunePlayer Player;
local string PlayerName;
if(Other.IsA('RunePlayer'))
{
Player = RunePlayer(Other);
PlayerName = Player.PlayerReplicationInfo.PlayerName;
RandomInt = Rand(8);

The next statment is called a switch statement (unsuprisingly enough!) and is an easy way of testing a lot of seperate conditions, the other alternative would be to use a large chain of if(..) elseif(...) statements such as.

if(RandomInt == 0)
{
//do something
}
elseif(RandomInt == 1)
{
//do something else
}
elseif(RandomInt == 2)
{
//do yet more stuff
}

The switch statement is much easier to read and involves less typing (always good!). The only thing to remember is to end each case with a break otherwise it will continue through until it hits one or finishes everything in the switch statement (although this might be something you want to do). In our case we check what number was generated in our Rand() function and display a message depending on what it was.

Someone wrote: switch(RandomInt)
{
case 0:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", AYE!");
break;
case 1:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", Are ye jesting?");
break;
case 2:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", That will never be!");
break;
case 3:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", Tis unlikely.");
break;
case 4:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", The mug is cloudy!");
break;
case 5:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", Indeed.");
break;
case 6:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", That will come to pass.");
break;
case 7:
BroadcastMessage("The Goblin of Truth tells "$PlayerName$", FEEL LOKI'S WRATH!!!");
break;
default:
break;
}

Lastly we return true so that the function that called UseTrigger() knows that we got through successfully and doesn't generate an error.

Someone wrote: defaultproperties
{
bDestroyable=False
bStatic=True
bJointsBlock=True
bJointsTouch=True
}

In the defaultproperties section we set several variables so that the statue can't be destroyed of moved around, it blocks things and allows you to stroke it! Now all you need do is compile it and create a new map to add the statue in.

Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: