Page 1 of 2

Basic DeusEx script explanations.

PostPosted: Mon Jun 19, 06 11:51 am
by Alex
In this topic, I will post random scripts, basic deus ex scripts, and explain what things do, and what some variables mean.

PostPosted: Mon Jun 19, 06 12:06 pm
by Alex
The first script, that can be seen below, is one of my favourites :)

//=============================================================================
// Sodacan.
//=============================================================================
class Sodacan extends DeusExPickup;

state Activated
{
function Activate()
{
// can't turn it off
}

function BeginState()
{
local DeusExPlayer player;

Super.BeginState();

The owner is the one who has this in his inventory. You must place DeusExPlayer() around it, to tell the script, that the owner must be a DeusExPlayer. Otherwise it will not find the function HealPlayer(), which is called further on in this script.

player = DeusExPlayer(Owner);
if (player != None)
player.HealPlayer(2, False);

It checks if the player exists, and if it does, it calls the function HealPlayer inside the player class. It has as variables 2 and False, the 2 is how much the player gets healed, and the False means that it wont give a medkit hiss, or recalculate the healing rate, when you activate it.

PlaySound(sound'MaleBurp');
This plays the oh so fun burping sound. No explanation needed?
UseOnce();
Whe you call this, the item gets deleted.
}
Begin:
}



defaultproperties
{
maxCopies=10
bCanHaveMultipleCopies=True
bActivatable=True
ItemName="Soda"
ItemArticle="some"
PlayerViewOffset=(X=30.000000,Z=-12.000000)
PlayerViewMesh=LodMesh'DeusExItems.Sodacan'
PickupViewMesh=LodMesh'DeusExItems.Sodacan'
ThirdPersonMesh=LodMesh'DeusExItems.Sodacan'
LandSound=Sound'DeusExSounds.Generic.MetalHit1'
Icon=Texture'DeusExUI.Icons.BeltIconSodaCan'
largeIcon=Texture'DeusExUI.Icons.LargeIconSodaCan'
largeIconWidth=24
largeIconHeight=45
Description="The can is blank except for the phrase 'PRODUCT PLACEMENT HERE.' It is unclear whether this is a name or an invitation."
beltDescription="SODA"
Mesh=LodMesh'DeusExItems.Sodacan'
CollisionRadius=3.000000
CollisionHeight=4.500000
Mass=5.000000
Buoyancy=3.000000
}



Now we involve the functions that get called in this script.

HealPlayer();
This can be found in DeusEx.DeusExPlayer.
// ----------------------------------------------------------------------
// HealPlayer()
// ----------------------------------------------------------------------

function int HealPlayer(int baseHealPoints, optional Bool bUseMedicineSkill)
{
As you can see, it has 2 variables in this function. The second one is optional, so you don't have to include this variable, so you can call this function on 2 ways:
HealPlayer(2);
HealPlayer(2,False/True);

local float mult;
local int adjustedHealAmount, aha2, tempaha;
local int origHealAmount;
local float dividedHealAmount;
These are variables that will be used in this function. You cannot call these variables outside the function, since it will not recognize them as declared variables. Take a good look at the word 'local'.

If you have bUseMedicineSkill = True in the function, it will recalculate the healing amount, since, if you have a high/low medkit skill, your medkit heals more/less.
if (bUseMedicineSkill)
adjustedHealAmount = CalculateSkillHealAmount(baseHealPoints);
else
adjustedHealAmount = baseHealPoints;

origHealAmount = adjustedHealAmount;

if (adjustedHealAmount > 0)
{
And if you use a medkit --> UseMedicineSkill, it will give the sound :)
if (bUseMedicineSkill)
PlaySound(sound'MedicalHiss', SLOT_None,,, 256);

// Heal by 3 regions via multiplayer game
if (( Level.NetMode == NM_DedicatedServer ) || ( Level.NetMode == NM_ListenServer ))
{
// DEUS_EX AMSD If legs broken, heal them a little bit first
if (HealthLegLeft == 0)
{
aha2 = adjustedHealAmount;
if (aha2 >= 5)
aha2 = 5;
tempaha = aha2;
adjustedHealAmount = adjustedHealAmount - aha2;
HealPart(HealthLegLeft, aha2);
HealPart(HealthLegRight,tempaha);
mpMsgServerFlags = mpMsgServerFlags & (~MPSERVERFLAG_LostLegs);
}
HealPart(HealthHead, adjustedHealAmount);

if ( adjustedHealAmount > 0 )
{
aha2 = adjustedHealAmount;
HealPart(HealthTorso, aha2);
aha2 = adjustedHealAmount;
HealPart(HealthArmRight,aha2);
HealPart(HealthArmLeft, adjustedHealAmount);
}
if ( adjustedHealAmount > 0 )
{
aha2 = adjustedHealAmount;
HealPart(HealthLegRight, aha2);
HealPart(HealthLegLeft, adjustedHealAmount);
}
}
else
{
HealPart(HealthHead, adjustedHealAmount);
HealPart(HealthTorso, adjustedHealAmount);
HealPart(HealthLegRight, adjustedHealAmount);
HealPart(HealthLegLeft, adjustedHealAmount);
HealPart(HealthArmRight, adjustedHealAmount);
HealPart(HealthArmLeft, adjustedHealAmount);
}

GenerateTotalHealth();

adjustedHealAmount = origHealAmount - adjustedHealAmount;

if (origHealAmount == baseHealPoints)
{
if (adjustedHealAmount == 1)
ClientMessage(Sprintf(HealedPointLabel, adjustedHealAmount));
else
ClientMessage(Sprintf(HealedPointsLabel, adjustedHealAmount));
}
else
{
ClientMessage(Sprintf(HealedPointsLabel, adjustedHealAmount));
}
}

return adjustedHealAmount;
}

I didn't explain this entire function, only parts. Otherwise this post will become too big.


The PlaySound() function, is declared in the Engine.Actor class.

native(264) final function int PlaySound
(
sound Sound,
optional ESoundSlot Slot,
optional float Volume,
optional bool bNoOverride,
optional float Radius,
optional float Pitch
);

Unfortunately, this is a native function. So that means that it is coded in Engine.dll.
You can see all variables here. It is not really important at the moment.

Now the function UseOnce();
This can be found in DeusEx.DeusExPickUp.
// ----------------------------------------------------------------------
// UseOnce()
//
// Subtract a use, then destroy if out of uses
// ----------------------------------------------------------------------

function UseOnce()
{
local DeusExPlayer player;

player = DeusExPlayer(Owner);
NumCopies--;

Reduce the number of copies you have

if (!IsA('SkilledTool'))
GotoState('DeActivated');


if (NumCopies <= 0)
{
Do you have 0 copies of the item? Or even less? Then destroy it. Also said, it will be deleted, and the item you will have in your hand, will be nothing.
if (player.inHand == Self)
player.PutInHand(None);
Destroy();
}
else
{
If you do have 1 or more copies of the item, update your belt, so you can see you used a sodacan.
UpdateBeltText();
}
}


Well, this is it kinda. I am not experienced with tutorials or whatsoever, so if something, even ANYTHING, is unclear, just ask! I will answer it :)

PostPosted: Mon Jun 19, 06 7:19 pm
by MainMan
Just a note of preference, but I think that it's easier to read when code is set out like this:
Code: Select all
Function A()
{
   if(a != 0)
   {
      if(a <= 5)
      {
         Owned();
      }
   }
}


rather than

Code: Select all
Function A()
{
if(a != 0)
{
if(a <= 5)
{
Owned();
}
}
}

PostPosted: Mon Jun 19, 06 7:27 pm
by Alex
I copy pasted the script straight from the file. And it doesn't show tabs in the forum :)

PostPosted: Mon Jun 19, 06 7:53 pm
by DarkKnight
~[A]lex~ wrote:I copy pasted the script straight from the file. And it doesn't show tabs in the forum :)


str_replace('\t', " ", $post);

You know it must be done.

PostPosted: Mon Jun 19, 06 9:15 pm
by Allan
But... using the Tab key switches from the text box, to the Preview box. So the only way to use Tab properly is to Copy/Paste it over and over.

PostPosted: Mon Jun 19, 06 9:24 pm
by Imperial
Could you explain the meanings of { and }, and what they represent?

PostPosted: Mon Jun 19, 06 10:13 pm
by AgentSmyth
Oh I know this one...

They are simply things that keep the code seperate from each other i.e.

Say you want to have 2 different functions...one to...I dunno set up a timer and the other to display the time you don't want the codes running into each other, so you put these at the beggining and end of each function to declare where each function starts and ends...it also works the same with the conditionals else, if, switch.

For example
Code: Select all
function starttime()
{
Insert Code here
}

function show time()
{
if (insert condition here)
   {
   insert events here
   }
else
   {
   insert events here
   }
}



Hope that helped :lol:

PostPosted: Tue Jun 20, 06 5:43 am
by Mr. Tastix
Interesting... Very interesting... Is it allowed if we take notes of this?

PostPosted: Tue Jun 20, 06 7:20 am
by Alex
Quite logical eh :)

PostPosted: Tue Jun 20, 06 7:39 am
by Mr. Tastix
~[A]lex~ wrote:Quite logical eh :)


Yes, but that doesn't really answer my question, lol.

PostPosted: Tue Jun 20, 06 7:40 am
by Alex
~Psychotic~ wrote:
~[A]lex~ wrote:Quite logical eh :)


Yes, but that doesn't really answer my question, lol.

Yes it's allowed... and that should be logical :)

PostPosted: Tue Jun 20, 06 8:46 am
by Dae
AgentSmyth wrote:Oh I know this one...

They are simply things that keep the code seperate from each other i.e.

Say you want to have 2 different functions...one to...I dunno set up a timer and the other to display the time you don't want the codes running into each other, so you put these at the beggining and end of each function to declare where each function starts and ends...it also works the same with the conditionals else, if, switch.

For example
Code: Select all
function starttime()
{
Insert Code here
}

function show time()
{
if (insert condition here)
   {
   insert events here
   }
else
   {
   insert events here
   }
}



Hope that helped :lol:

I use UltraEdit 32 with Unreal script highlighting. I highly recommend everyone to get this program - it's perfect!

PostPosted: Tue Jun 20, 06 8:47 am
by Alex
I use Notepad, without any thing extra :lol:

PostPosted: Tue Jun 20, 06 9:30 am
by DarkKnight
~[A]lex~ wrote:I use Notepad, without any thing extra :lol:


Syntax highlighting is the greatest thing since sliced bread.

PostPosted: Tue Jun 20, 06 9:33 am
by Allan
No, Deus Ex is the greatest thing since sliced bread, and syntax highlighting is the greatest thing since Deus Ex =)

But still, I'd say this is a program worth looking at =)

(Oh, and I use UnrealEd's compiler. It's just faster to pick up on my mistakes(And nowadays, I make a lot of them ;) ) )

PostPosted: Tue Jun 20, 06 12:04 pm
by AgentSmyth
my problem is i just don't know where to begin...or end...or write code...o god :shock:
-exports all the classes and looks through frantically-
Nope still nothing :P

PostPosted: Tue Jun 20, 06 2:40 pm
by DarkKnight
AgentSmyth wrote:my problem is i just don't know where to begin...or end...or write code...o god :shock:
-exports all the classes and looks through frantically-
Nope still nothing :P


The first thing anyone wanting to learn how to script or code should know is where to start.

In the case of DX, the first step you need to do is get DX to load it. From there, the rest is utility functions.

Also, Alex, could you PM me the smuggler code? I'm interested to see the UI code. :)

PostPosted: Tue Jun 20, 06 4:40 pm
by MainMan
Notepad all the way. Easy, loads in 2 seconds, and no fancy colours.

PostPosted: Tue Jun 20, 06 4:57 pm
by Alex
Yup, same. I don't care if my uccmake gives 569385 errors. I need to fix em anyways, so 1. Use uccmake to find em 2. Have more lag using a special uber 1337 notepad or w/e.

PostPosted: Tue Jun 20, 06 5:05 pm
by AgentSmyth
what do you's do for inspiration...and what would be the best and quickest way to learn scripting? :?

PostPosted: Tue Jun 20, 06 5:25 pm
by Alex
AgentSmyth wrote:what do you's do for inspiration...and what would be the best and quickest way to learn scripting? :?

I look at other games, or ideas just pop up.
And I looked at scripts, I read them. First I need to know what something does (Example, a switch), then I read the script. And understand every bit of it.

PostPosted: Sat Sep 16, 06 1:29 pm
by Alistair
Its good to understand Object Orientated Programming, or algebra to be simple

PostPosted: Fri Nov 17, 06 6:46 am
by Ayleth
WOTgreal all the way!!!111two. seriously, it supports running dx with special switches, syntax highlighting, reverse lookup (ctrl-click on a word will try to bring you to its first mention) find in active document, find in all files, dude theres just too much to say about it. Anyone who wants to get hooked up, go to www.wotgreal.com. i also have a goody for those who really like the program. >=+D

PostPosted: Wed Mar 07, 07 11:47 pm
by Jon
How about a gas grenade? I'd like to see how the damage and vision impairment codes are made.

PostPosted: Fri May 25, 07 5:21 pm
by Alex
Sorry Jon, for the late response. Here it is, I think. I might post it unfinished, and post the rest later on.

Code: Select all
//=============================================================================
// GasGrenade.
//=============================================================================
class GasGrenade extends ThrownProjectile;

var float   mpBlastRadius;
var float   mpProxRadius;
var float   mpGasDamage;
var float   mpFuselength;

simulated function PreBeginPlay()
{
   Super.PreBeginPlay();

   if ( Level.NetMode != NM_Standalone )
   {
      blastRadius=mpBlastRadius;
      proxRadius=mpProxRadius;
      Damage=mpGasDamage;
      fuseLength=mpFuseLength;
      bIgnoresNanoDefense=True;
   }
}

defaultproperties
{
    mpBlastRadius=512.00
    mpProxRadius=128.00
    mpGasDamage=20.00
    mpFuselength=1.50
    fuseLength=3.00
    proxRadius=128.00
    AISoundLevel=0.00
    bBlood=False
    bDebris=False
    DamageType=TearGas
    spawnWeaponClass=Class'WeaponGasGrenade'
    ItemName="Gas Grenade"
    speed=1000.00
    MaxSpeed=1000.00
    Damage=10.00
    MomentumTransfer=50000
    ImpactSound=Sound'DeusExSounds.Weapons.GasGrenadeExplode'
    LifeSpan=0.00
    Mesh=LodMesh'DeusExItems.GasGrenadePickup'
    CollisionRadius=4.30
    CollisionHeight=1.40
    Mass=5.00
    Buoyancy=2.00
}

As you can see, there is nothing special in this projectile class.
Only the "DamageType=TearGas" defines something that has to do with gas.

Then we look in the Parent Class (ThrownProjectile) for matches with "DamageType" and "TearGas". We vind a good match in the state "Flying". You can override functions in this state. With states you can actually define one function multiple times, giving it different coding. We look at the function Explode() in the state Flying. In there, there is this bit:
Code: Select all
      if ((damageType=='TearGas') && (Role==ROLE_Authority))
         SpawnTearGas();

So if the damageType is TearGas, we call the function SpawnTearGas:
Code: Select all
function SpawnTearGas()
{
   local Vector loc;
   local TearGas gas;
   local int i;

   if ( Role < ROLE_Authority )
      return;

   for (i=0; i<blastRadius/36; i++)
   {
      if (FRand() < 0.9)
      {
         loc = Location;
         loc.X += FRand() * blastRadius - blastRadius * 0.5;
         loc.Y += FRand() * blastRadius - blastRadius * 0.5;
         loc.Z += 32;
         gas = spawn(class'TearGas', None,, loc);
         if (gas != None)
         {
            gas.Velocity = vect(0,0,0);
            gas.Acceleration = vect(0,0,0);
            gas.DrawScale = FRand() * 0.5 + 2.0;
            gas.LifeSpan = FRand() * 10 + 30;
            if ( Level.NetMode != NM_Standalone )
               gas.bFloating = False;
            else
               gas.bFloating = True;
            gas.Instigator = Instigator;
         }
      }
   }
}

We don't really need to know what it all does when we only want to know how someone gets damaged or get partially blinded. So we see something special:
"gas = spawn(class'TearGas', None,, loc);".
The class "TearGas" is being spawned! So we open up that class.

Code: Select all
//=============================================================================
// TearGas.
//=============================================================================
class TearGas extends Cloud;

defaultproperties
{
    DamageType=TearGas
    maxDrawScale=2.00
    Texture=WetTexture'Effects.Smoke.Gas_Tear_A'
}

As you can see, the DamageType is defined here aswell. The class is quite small, so we take a look at the parent class, Cloud.
We search for matches with "DamageType", as we don't get any results when we search for "TearGas".
We find this:
Code: Select all
function Timer()
{
   local Actor A;
   local Vector offset, dist;
   local Pawn apawn;

   if ( Level.NetMode != NM_Standalone )
   {
      // Use PawnList for multiplayer
      apawn = Level.PawnList;
      while ( apawn != None )
      {
         dist = apawn.Location - Location;
         if ( VSize(dist) < cloudRadius )
         {
            offset = apawn.Location;
            apawn.TakeDamage( Damage, Instigator, offset, vect(0,0,0), damageType );                                           
         }
         apawn = apawn.nextPawn;
      }
   }
   else
   {
      // check to see if anything has entered our effect radius
      // don't damage our owner
      foreach VisibleActors(class'Actor', A, cloudRadius)
         if (A != Owner)
         {
            // be sure to damage the torso
            offset = A.Location;
            A.TakeDamage(Damage, Instigator, offset, vect(0,0,0), damageType);
         }
   }
}

As you can see, the damage giving part is in Timer. This function has been activated in another function:
Code: Select all
function BeginPlay()
{
   Super.BeginPlay();

   // set the cloud damage timer
   SetTimer(damageInterval, True);
}

This means, the timer will run every damageInterval seconds, and it will loop, since that is set to True.
damageInterval=1.00, it is in the defaultproperties.
So we see that the timer checks every second if there are things in the radius that can be damaged, if so, damage it!

I will continue writing this later. But as you can understand TakeDamage() creates the damage part. If I can recall correctly, if you do a TakeDamage() with TearGas or Poison as damagetype, you get poisoned. But we'll see that later!

PostPosted: Fri May 25, 07 7:04 pm
by Ayleth
Nice work.

PostPosted: Sat Aug 18, 07 12:37 pm
by Andrievskaya Veronika
I'd like to know, what these functions are doing (detailed if possible :) :D ):

Code: Select all
(from CORE\Object.uc)

native(192) static final function     float Loge  ( float A );
native(193) static final function     float Sqrt  ( float A );
native(194) static final function     float Square( float A );
native(195) static final function     float FRand ();
native(244) static final function     float FMin  ( float A, float B );
native(245) static final function     float FMax  ( float A, float B );
native(246) static final function     float FClamp( float V, float A, float B );
native(247) static final function     float Lerp  ( float Alpha, float A, float B );
native(248) static final function     float Smerp ( float Alpha, float A, float B );


especially about FRand , FMin, FMax and FClamp.

PostPosted: Sat Aug 18, 07 12:58 pm
by Alex

PostPosted: Sat Aug 18, 07 12:59 pm
by Dae
I only knew loge, sqrt, square, frand, the rest had to look up here.

Andrievskaya Veronika wrote:Loge

natural logarithm (натуральный логарифм)

Andrievskaya Veronika wrote:Sqrt

it's the same even in Pascal!

square root (квадратный корень)

Andrievskaya Veronika wrote:Square

returns value in 2nd power (возводит в квадрат)

Andrievskaya Veronika wrote:FRand

a random number from 0 to 1 (рандомизатор от нуля до единицы)

FMin/FMax return the lower/higher values from A and B
(сравнивает A и B и возвращает либо максимальное (Fmax), либо минимальное значение (fmin))

Andrievskaya Veronika wrote:FClamp

wiki.beyondunreal.com wrote:If V is smaller than A, A is returned. If V is larger than B, B is returned. In any other case V is returned.


Andrievskaya Veronika wrote:Lerp

wiki.beyondunreal.com wrote:"Returns the linear interpolation between A and B."
The return value is calculated through something like this:
(B - A) * Alpha + A


Andrievskaya Veronika wrote:Smerp

wiki.beyondunreal.com wrote:Returns an Alpha-smooth nonlinear interpolation between A and B.
The return value seems to be calculated through something like this:
(-2 * (B - A) * Alpha ** 3) + (3 * (B - A) * Alpha ** 2) + A