Top Banner
Sega 500 Custom Scripted Actions Jeff “Ezeikeil” Giles [email protected]
73

Sega 500

Jan 02, 2016

Download

Documents

riley-foreman

Sega 500. Custom Scripted Actions. Jeff “Ezeikeil” Giles [email protected] http://gamestudies.cdis.org/~jgiles. Thus far. We’ve played with both Scripted events and sequences for our pawns and found them to be quite similar. - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Sega 500

Sega 500

Custom Scripted Actions

Jeff “Ezeikeil” [email protected]://gamestudies.cdis.org/~jgiles

Page 2: Sega 500

Thus far

We’ve played with both Scripted events and sequences for our pawns and found them to be quite similar.

Not to mention that we had some fun making our bot get squashed and run in circles.

Page 3: Sega 500

Today

Although the current actions list is quite extensive, without surprise, there is some functionality which is not included.

So we’re going to build our own.

Page 4: Sega 500

What are we building?

Well, one of the few things thing that I found I could not do in the list was cause the creation of a pawn with AI.

Sure, we could create the pawn, but there was no attachment to a controller.

Page 5: Sega 500

What are we building?

I’ve found 2 methods that work well to create a pawn at a specific location and both are fairly straight forward.

The first relies almost exclusively on the current functionality for adding bots

Page 6: Sega 500

What are we building?

The second, has a bit more to it, but if gives more direct control over the pawns creation.

Page 7: Sega 500

Setup

Both of the classes derive from scriptedaction

class Action_CreateBot extends ScriptedAction;

These will auto-magically appear in the pull down menu of our actions list in the editor.

Page 8: Sega 500

About Scripted Actions

Actually, setting up a new action is really quite easy.

All the magic happens around one function:

function bool InitActionFor(ScriptedController C)

Page 9: Sega 500

About Scripted Actions

Although there are a one or two cases where it is not used, it’s fairly safe to say that anything we want to implement will be called from here.

Page 10: Sega 500

The easy way

Starting by getting the bot into the game at any player start point, we just need to call a few function that already exist in our game type.

Page 11: Sega 500

The easy way

The trick lies in accessing these functions. The ones we’re after are:

SpawnBot. RestartPlayer.

Both of which are defined in the Deathmatch game type.

Page 12: Sega 500

The easy way

The nice part is that any gametype we use will have this class as a parent.

Page 13: Sega 500

The easy way

So how do we get there from here?

As you already know, the game is accessible from just about anywhere in the code.

It just takes some typecasting.

Page 14: Sega 500

The easy way

I our case, we’re given a controller, which can see the level.

And the level knows about the game, so we can safely cast to our parent class.

DeathMatch(c.Level.game)

Page 15: Sega 500

The easy way

Cool! So getting our bots in is just a matter of

accessing these functions…

local bot newBot;

newBot = DeathMatch(c.Level.game).SpawnBot();c.Level.game.RestartPlayer(NewBot);

Page 16: Sega 500

The easy way

And this spawns our dude into the level when this script is hit.

And because we’re using the existing functions, all the initializations are taken care of for us…gota like that!

Page 17: Sega 500

The easy way

But spawning him at a random start point is not always what we want.

So how to we tell UT where to spawn something?

Page 18: Sega 500

The easy way

Well UT’s spawn function takes parameters, one of which is location…should be simple no?

Just do an allactors search and match up a tag to an object…simple.

Page 19: Sega 500

The easy way

But there’s a problem. We don’t have an allactors iterator…can’t see it, can’t access it.

We derive off object, not actor where all our iterators are defined.

…so, does this mean we’re screwed?

Page 20: Sega 500

The easy way

Well, no…the cost of admission just goes up.

Object has a single iterator for us to use.

AllObjects

<Shudder>

Page 21: Sega 500

The easy way

So we can get to any object’s tag, we just have to iterate over ALL the objects in the game.

Expensive.

Page 22: Sega 500

The easy way

It works just like any other iterator

native(197) final iterator function AllObjects

(class baseClass, out Object obj);

Page 23: Sega 500

The easy way

So how do we us it then…

And inside the InitActionFor function:

var(AIBOT) name loctag; // what we’re looking for

Page 24: Sega 500

The easy way

foreach AllObjects(class'Actor', A){ if( a.Tag==locTag ) { newBot = DeathMatch(c.Level.game).SpawnBot(); c.Level.game.RestartPlayer(NewBot); NewBot.SetLocation(A.Location); newbot.Pawn.SetLocation(A.Location) }}

Page 25: Sega 500

The easy way

And TA-DA! It’s in! Spawn anywhere.

But there’s a *small* catch to this method.

The restartplayer call causes a spawn at the player start in the conventional manner

Page 26: Sega 500

The easy way

An then we set the players location to where we want him.

However, this leaves the spawn effect at the start point.

Page 27: Sega 500

The easy way

So this works, but we can’t have this effect happening where the player can see it.

On to method number two, which is quite similar. We just change the guts of the InitActionFor function.

Page 28: Sega 500

A better way

And add a bit more in the set up.

This method also allows us to define which controllers and pawn we want to use.

var(AIBOT) name objecttag; //Where to spawnvar(AIBOT) class<bot> bType; //What Bot typevar(AIBOT) class<Pawn> pType; //What pawn Type

Page 29: Sega 500

A better way

And in the InitActionFor function, we redefine it as:

function bool InitActionFor(ScriptedController C){ local bot newBot; local Pawn newPawn; local actor A;

local UnrealTeamInfo BotTeam; local RosterEntry Chosen;

Page 30: Sega 500

A better way

The UnrealTeamInfo and RosterEntry are needed to properly initialize the bot.

Everything else is a handle to an object that we’ll create here.

Page 31: Sega 500

A better way

We keep the same search method…not much of a choice

foreach AllObjects(class'Actor', A) { if( a.Tag==locTag ) {

Page 32: Sega 500

A better way

Spawn a pawn and a controller at the desired loaction, based on our search result (Actor a)

newBot = c.Level.Spawn(bType,,,a.Location, a.Rotation);newPawn = c.Level.Spawn(pType,,,a.Location, a.Rotation);

Page 33: Sega 500

A better way

So they’re both in the game but need to be added to the game roster and initialized

BotTeam=DeathMatch(c.Level.game).GetBotTeam();Chosen =BotTeam.ChooseBotClass();Chosen.Init();

DeathMatch(c.Level.game).InitializeBot(newBot,BotTeam , Chosen);

Page 34: Sega 500

A better way

And lastly, we need the controller to own the pawn. This is done with the Posses function.

newBot.Possess(newPawn);

Page 35: Sega 500

A better way

Give it a run, it works nice…

...but there’s something

missing…

Page 36: Sega 500

A better way

The pawn comes in, with a brain, great!

But where the heck is the gun!

Page 37: Sega 500

A better way

And, notice that once you frag them, spawn back into the game with all there toys.

So we missed something…

Page 38: Sega 500

A better way

Actually, just one line…ain’t that always the way?

If you route through the deathmatch class you find this

function AddDefaultInventory( pawn PlayerPawn )

Page 39: Sega 500

A better way

And it does, just what the name says…

Accessing it is nothing new as well,

DeathMatch(c.Level.game).AddDefaultInventory(newPawn);

Page 40: Sega 500

A better way

Lastly, in our default properties, we need to set the ActionString to something meaningful.

ActionString="Spawn EzeBot"

Page 41: Sega 500

A better way

As best I can tell, the action string is used exclusively for debug purposes and this is the text that is thrown to the screen.

This is done from the ScriptedSequence object. Beyond that, I’ve not found any functionality.

Page 42: Sega 500

That’s all well and good…

But, continually adding bots is only so much fun.

The real fun lies in killing them off

Page 43: Sega 500

Killing our pawn

So, from our scripted sequence, time to do that.

This part is actually really easy if you controller already has a pawn associated to it…Well go over how to get one in a minute if it doesn’t.

Page 44: Sega 500

Killing our pawn

So the new action I defined as:

class Action_Gib extends ScriptedAction;

function bool InitActionFor(ScriptedController C){ c.Pawn.ChunkUp(c.Pawn.Rotation, 1.0); c.Pawn.PlaySound(sound'PlayerSounds.Final.Giblets1');

return true; //must return true or UT crashes}

Page 45: Sega 500

Killing our pawn

Yup, that’s the whole thing.

The actual kill is build into the pawn already, it’s just a matter of accessing it.

Can you guess what it does?

Page 46: Sega 500

Killing our pawn

Before:

Page 47: Sega 500

Killing our pawn

After:

SPLAT!

However, I am a bid confused as to how he got 2 skulls though…

Page 48: Sega 500

Killing our pawn

Yup, it turns our pawn into a bunch of giblets.

The best thing is, you can now just add this to the list of Scripted events for your AIScript.

Page 49: Sega 500

Killing our pawn

So long as you have a pawn associated with it that is…

Page 50: Sega 500

Integration into Gameplay

Ok, I believe that it’s great for telling stories to the player and watching things happen.

But can the player interact with it?

In a word, yes.

Page 51: Sega 500

Integration into Gameplay

And this is where the code monkeying starts to take place.

One of the fun levels in the original UT was DM-pressure…

Page 52: Sega 500

Integration into Gameplay

You had to go into a pressure chamber to get the rocket launcher.

Page 53: Sega 500

Integration into Gameplay

However, while in there, you could be sealed in by the push of a button which would cause the player to pop like a ballon.

Tones-o-fun !

Page 54: Sega 500

Integration into Gameplay

You guessed it, we’re going to build something similar.

Just an FYI, something like this is much better suited to a volume or a zone, this is just one possible example.

Page 55: Sega 500

Integration into Gameplay

The first thing I did was set up a level so the we could test this out fairly easily…

Starting with an oddly shaped brush which was built using the deintersect tool.

Page 56: Sega 500

Integration into Gameplay

I’m going to use this so I can box my enemy pawn into a corner…

Then, used a transparent texture so I could see the bot get splattered.

Page 57: Sega 500

Integration into Gameplay

I also left a gap on the edges so I could use a translocator to get out.

But too small for a bot…

Page 58: Sega 500

Integration into Gameplay

Now, over to the code.

The search method we’re going to use here is very similar to the one we just used to find the matching tag.

Using all objects <shudder>

Page 59: Sega 500

Integration into Gameplay

But we have to put some logic in to to a “radius search”.

class Action_FindNewPawn extends ScriptedAction;

var()int radius;

DefaultProperties{ radius=128}

Page 60: Sega 500

Integration into Gameplay

Next up is a simpler iteration over all the objects <shudder> and test to find the closest one.

Page 61: Sega 500

Integration into Gameplayfunction bool InitActionFor(ScriptedController C){ local pawn p, closest; local float dist, closestDist;

foreach allobjects(class'Pawn', p) { if(closest!=none) { dist=Vsize(p.location-c.Location); if(dist < closestDist) { closest=p; closestDist=dist; } }

Page 62: Sega 500

Integration into Gameplay

else { closest=p; closestDist=Vsize(p.location-c.Location); } }

if( closestDist<radius) c.Pawn=closest;

return true; //must return true or UT crashes}

Page 63: Sega 500

Integration into Gameplay

Nothing overly fancy…

But, now the fun stuff…it’s ready to use.

Jumping back to the editor, we set up our scripted triggers.

Page 64: Sega 500

Integration into Gameplay

I place the scripted trigger in my room and the activation trigger a safe distance away.

Activation trigger

Scriptedtrigger

Page 65: Sega 500

Integration into Gameplay

And then set up my scripts:

Page 66: Sega 500

Integration into Gameplay

Wait for the activation trigger

Page 67: Sega 500

Integration into Gameplay

Spawn some special effects for show…

Page 68: Sega 500

Integration into Gameplay

Find the closed pawn which is within 230 UU’s

Page 69: Sega 500

Integration into Gameplay

And then call my ready-made gib function.

Page 70: Sega 500

Integration into Gameplay

Lastly…do it again

Page 71: Sega 500

Integration into Gameplay

Do an addbots console command and …poof!

Caged like a rat!

Page 72: Sega 500

Integration into Gameplay

Then when you hit the trigger,

ZAP!...no more bot.

Page 73: Sega 500

That’s all folks

We’ve now customized our own action scripts, hope ya found it fun…