PDA

View Full Version : customed kismet sequence?



gerrardx
11-22-2009, 09:19 AM
wondering whether I can use unrealscript to program my own kismet sequence?

Wormbo
11-22-2009, 09:52 AM
Yes, custom Kismet actions, conditions and events can be created as UnrealScript classes. The corresponding base classes you need to extend are SequenceAction (http://wiki.beyondunreal.com/UE3:SequenceAction_(UDK)), SequenceCondition (http://wiki.beyondunreal.com/UE3:SequenceCondition_(UDK)) and SequenceEvent (http://wiki.beyondunreal.com/UE3:SequenceEvent_(UDK)), respectively.

Custom SequenceActions can either automatically call a "handler" function on all actors passed in as Targets, or perform a custom action in its Activated() event function. SequenceConditions do their stuff in the Activated() function as well, but don't have the handler function magic.
SequenceEvents must be activated from somewhere in your actor or UI script code. The event nodes can either be associated with one of the mapper-placed actors (or dynamically via the Attach To Event" action) or be level-wide events.

Unfortunately, many of the built-in actions either call a handler function or have a native implementation, so examples are rare. For UT3 Jailbreak, however, we have coded a whole bunch of new Kismet nodes. For example:


/************************************************** ****************************
Makes a bot crouch. Combination with AI Freeze action is recommended to make
the bot stay in place and not uncrouch.

Creation date: 2009-09-18 09:39
Last change: $Id: JBSeqAct_AICrouch.uc 198 2009-09-21 19:15:59Z Wormbo $
Copyright (c) 2009, Wormbo
************************************************** ****************************/

class JBSeqAct_AICrouch extends SequenceAction;


/**
Tell the bot to crouch/uncrouch.
*/
event Activated()
{
local Pawn P;
local int i;
local bool bCrouch;

if (InputLinks[0].bHasImpulse) {
bCrouch = True;
} else if (!InputLinks[1].bHasImpulse) {
return;
}

for (i = 0; i < Targets.Length; ++i) {
P = Pawn(Targets[i]);
if (P == None && Controller(Targets[i]) != None)
P = Controller(Targets[i]).Pawn;

if (P != None && P.bCanCrouch)
P.ShouldCrouch(bCrouch);
}
}


//================================================== ===========================
// Default values
//================================================== ===========================

defaultproperties
{
ObjName = "AI Crouch"
ObjCategory = "Jailbreak"
ObjClassVersion = 1 // increment for incompatible changes!
bCallHandler = False
bAutoActivateOutputLinks = False

InputLinks.Empty
InputLinks.Add((LinkDesc="Crouch"))
InputLinks.Add((LinkDesc="Uncrouch"))

VariableLinks[0] = (LinkDesc="Pawn",MaxVars=1)
}

This is a Kismet action without handler function that is supposed to make bots crouch.

Another example, this time with handler function:


/************************************************** ****************************
Cancels a scheduled arena fight that hasn't started yet.
(Use "End Arena Fight" instead to stop fights in progress.)

Creation date: 2009-08-05 18:14
Last change: $Id: JBSeqAct_CancelArenaFight.uc 130 2009-08-05 22:23:37Z Wormbo $
Copyright (c) 2009, Wormbo
************************************************** ****************************/

class JBSeqAct_CancelArenaFight extends SequenceAction;


//================================================== ===========================
// Default values
//================================================== ===========================

defaultproperties
{
ObjName = "Cancel arena fight"
ObjCategory = "Jailbreak"
ObjClassVersion = 1 // increment for incompatible changes!

VariableLinks(0) = (LinkDesc="Arena fight")
}

The corresponding handler function in the actor passed to the action as "Arena fight" is defined as "function OnCancelArenaFight(JBSeqAct_CancelArenaFight Action)" in this case.

A custom condition for testing whether a player is a bot:


/************************************************** ****************************
JBSeqCont_IsBot

Creation date: 2009-08-01 20:37
Last change: $Id: JBSeqCond_IsBot.uc 116 2009-08-01 22:01:10Z Wormbo $
Copyright (c) 2009, Wormbo
************************************************** ****************************/

class JBSeqCond_IsBot extends SequenceCondition;


var Actor Player;


/**
Checks the player and activates the corresponding output.
*/
event Activated()
{
local JBPlayerReplicationInfo PRI;

if (Pawn(Player) != None) {
PRI = JBPlayerReplicationInfo(Pawn(Player).PlayerReplica tionInfo);
}
else if (Controller(Player) != None) {
PRI = JBPlayerReplicationInfo(Controller(Player).PlayerR eplicationInfo);
}
else {
ScriptLog(Self $ " - No player specified!");
}

OutputLinks[(PRI != None && PRI.bBot) ? 0 : 1].bHasImpulse = true;
}


//================================================== ===========================
// Default values
//================================================== ===========================

defaultproperties
{
ObjName = "Is a bot?"
ObjCategory = "Jailbreak"
ObjClassVersion = 1 // increment for incompatible changes!

OutputLinks(0) = (LinkDesc="Yes")
OutputLinks(1) = (LinkDesc="No")
VariableLinks.Add((ExpectedType=Class'Engine.SeqVa r_Object',LinkDesc="Player",PropertyName=Player,MaxVars=1))
}



And a custom event:


/************************************************** ****************************
Global execution event. This event is triggered when all players of one team
have been captured without the other team being captured as well.

Output:
; Start execution : Fires when the game stops the match to execute the captured team.
; All prisoners dead : Fires after all prisoners have died. This signals the end of the execution.

Variables:
; Capturing Player : Contains the player that sent the last player of the captured team to jail. This could be a member of any team, even the last captured player him/herself.
; Captured Team : Contains the number of the captured team. (Red = 0, Blue = 1)
; Captured Player : Contains the last captured player on the captured team. This will always be the last player on the captured team, even if a player from the other team died afterwards.

The actual end of an execution sequence is determined not only by the death of
the last executed prisoner, but also through the "End Execution" action,
JBSeqAct_EndExecution. If there is no "End Execution" action connected to any
"Execution" event, it is implied to be attached directly to the "All prisoners
dead" output connector. However, this means if you use "End Execution" you will have
to connect it from every possible end of your execution script.

Creation date: 2008-08-11 17:51
Last change: $Id: JBSeqEvent_Execution.uc 152 2009-08-21 11:24:09Z Wormbo $
Copyright (c) 2008, Wormbo
************************************************** ****************************/

class JBSeqEvent_Execution extends SequenceEvent;


//================================================== ===========================
// Variables
//================================================== ===========================

/** The player, turret or monster who sent the last player of the captured team to jail. */
var Controller CapturingPlayer;
/** The team that got captured. */
var int CapturedTeam;
/** The last player of the captured team who was sent to jail. */
var Controller CapturedPlayer;


/**
Sanity check.
*/
event RegisterEvent()
{
if (bClientSideOnly) {
`log(Self $ " must not be clientside-only!",, 'JailbreakWarning');
}
if (bPlayerOnly) {
`log(Self $ " must not be player-only!",, 'JailbreakWarning');
bPlayerOnly = False;
}
}


//================================================== ===========================
// Default values
//================================================== ===========================

defaultproperties
{
ObjName = "Execution"
ObjCategory = "Jailbreak"
ObjClassVersion = 3 // increment for incompatible changes!
bPlayerOnly = false
MaxTriggerCount = 0

OutputLinks(0)=(LinkDesc="Start execution")
OutputLinks(1)=(LinkDesc="All prisoners dead")

VariableLinks.Empty
VariableLinks.Add((ExpectedType=class'SeqVar_Objec t',LinkDesc="Capturing Player",PropertyName=CapturingPlayer,bWriteable=True))
VariableLinks.Add((ExpectedType=class'SeqVar_Int', LinkDesc="Captured Team",PropertyName=CapturedTeam,bWriteable=True))
VariableLinks.Add((ExpectedType=class'SeqVar_Objec t',LinkDesc="Captured Player",PropertyName=CapturedPlayer,bWriteable=True))
}

Note that events can perform some sanity checks in their RegisterEvent() function.
This event is not tied to any specific actor. The following code is used to activate it:


// activate execution event
GameSeq = WorldInfo.GetGameSequence();
if (GameSeq != None) {
EventOutLinks[0] = 0;
GameSeq.FindSeqObjectsByClass(class'JBSeqEvent_Exe cution', True, ExecutionEvents);
foreach ExecutionEvents(ExecutionEvent) {
JBExecutionEvent = JBSeqEvent_Execution(ExecutionEvent);
if (JBExecutionEvent != None && JBExecutionEvent.CheckActivate(WorldInfo, None, True, EventOutLinks)) {
JBExecutionEvent.CapturingPlayer = LastCaptureKiller[CapturedTeam];
JBExecutionEvent.CapturedTeam = CapturedTeam;
JBExecutionEvent.CapturedPlayer = LastCaptureVictim[CapturedTeam];
JBExecutionEvent.CheckActivate(WorldInfo, None, False, EventOutLinks);
}
}
}

TheSpaceMan
11-22-2009, 10:12 AM
in your code you have the following.


if (InputLinks[0].bHasImpulse)
{
bCrouch = True;
}
else if (!InputLinks[1].bHasImpulse)
{
return;
}


These are added like this in the default props.


InputLinks.Add((LinkDesc="Crouch"))
InputLinks.Add((LinkDesc="Uncrouch"))

The thing i wonder, since InputLinks[0] is the Link we added with name LinkDesc="Crouch".

Is there a way get one of the InputLinks based on the Name of the link.
Seems like this could be much clearer in the long run.

Wormbo
11-22-2009, 01:14 PM
You could probably use something like the following:

InputLinks[InputLinks.Find('LinkDesc',"Crouch")].bHasImpulse
Or use constants or defines instead of index numbers and specify the defprops using the array index syntax "x[y]=z" instead of the array modification syntax "x.add(z)" I used.

gerrardx
11-23-2009, 04:05 AM
You are THE ONE!!!!