NewsUnrealEdFilesModsFragBULiandri Archives
BeyondUnreal Forums

Go Back   BeyondUnreal Forums > Unreal Development > Coding

Reply
 
Thread Tools Display Modes
Old 3rd Aug 2011, 03:18 AM   #1
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
Bone Rotating (client side)

Hello, how can i get bone rotation on client?
I attempt to do SetBoneRotation, but it doesn't work on client, for example on non-dedicated server or single game bone is rotating well.
Engine: UE2 (Postal2 edition)

Last edited by EvilT-ModZ; 3rd Aug 2011 at 03:20 AM.
EvilT-ModZ is offline   Reply With Quote
Old 7th Aug 2011, 02:03 AM   #2
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
p.s: script is very simple
Code:
class mgunweapon extends weapon;
const ROT_BONE = 'barrel';
simulated function DoRotate() {
local rotator rotme;
rotme.roll=32768;
SetBoneRotation('ROT_BONE', rotme, 0, 1);
}
function ProjectileFire() {
DoRotate();
}
for example it fully works on ut2004's clients
EvilT-ModZ is offline   Reply With Quote
Old 7th Aug 2011, 03:02 AM   #3
Wormbo
 
 
Wormbo's Avatar
 
Join Date: Jun. 4th, 2001
Location: Germany
Posts: 5,771
I'm pretty sure the third parameter of SetBoneRotation() should be set to 1 (or omitted, as 1 is the default) for an effect to become visible. And for a barrel, I think you actually want local space, in other words omit the fourth parameter as well or set it to 0.
__________________
Wormbo's UT/UT2004/UT3 mods | YouTube channel | PlanetJailbreak/JDN | Unreal Wiki | Liandri Archives
Everything you ever wanted to know about replication| UnrealScript security considerations
<elmuerte> you shouldn't do all-nighters, it's a waste of time and effort
<TNSe> nono
<TNSe> its always funny to find code a week later you dont even remember writing
<Pfhoenix> what's worse is when you have a Star Wars moment
<Pfhoenix> "Luke! I am your code!" "No! Impossible! It can't be!"
Wormbo is offline   Reply With Quote
Old 7th Aug 2011, 05:49 AM   #4
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
Quote:
Originally Posted by Wormbo View Post
I'm pretty sure the third parameter of SetBoneRotation() should be set to 1 (or omitted, as 1 is the default) for an effect to become visible. And for a barrel, I think you actually want local space, in other words omit the fourth parameter as well or set it to 0.
Thanks for advise but doesn't work on client(
EvilT-ModZ is offline   Reply With Quote
Old 7th Aug 2011, 05:54 AM   #5
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
I found that SetBoneRotation not simulated like in ut2003/2004
Code:
native final function SetBoneRotation( name BoneName, optional rotator BoneTurn, optional int Space, optional float Alpha );
so, it's imposible to do bone rotating on client without rewriten class Actor? :/
EvilT-ModZ is offline   Reply With Quote
Old 7th Aug 2011, 11:03 AM   #6
meowcat
nothing new under the sun
 
meowcat's Avatar
 
Join Date: Jun. 7th, 2001
Posts: 761
I don't know about Postal2, but in UT2004, the equivalent function of ProjectileFire (DoFireEffect/SpawnProjectile) was only executed on the server (in the weaponFire class, not weapon), so your DoRotate function would only be called there, not on the client. To run on the client you should call your DoRotate function from the appropriate point in the PlayFiring function instead (which should be simulated no matter where it is located).
__________________
"What do you mean it doesn't exist clientside?"
Meowcat's Mods for UT2K4:
Yet Another Real-life Mod: Class-based play, generic realistic weapons, unoriginal gameplay, w/ cheap COD4 knockoff, parkour player moves
TD Vehicles v125: HMMWV, MI4Hound, Black Hawk & AH-6 Helicopters, Motorcycle, IFAV Jeep, Abrams Tank
Jetpacks for UT2k4!

Last edited by meowcat; 7th Aug 2011 at 11:04 AM.
meowcat is offline   Reply With Quote
Old 7th Aug 2011, 11:55 PM   #7
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
Quote:
Originally Posted by meowcat View Post
I don't know about Postal2, but in UT2004, the equivalent function of ProjectileFire (DoFireEffect/SpawnProjectile) was only executed on the server (in the weaponFire class, not weapon), so your DoRotate function would only be called there, not on the client. To run on the client you should call your DoRotate function from the appropriate point in the PlayFiring function instead (which should be simulated no matter where it is located).
Thank you for advise. So, i already attempt to do bone rotation for pawn on the Tick, and it too doesn't work

Code:
simulated function Tick(float DeltaTime) {
local rotator rotme;
rotme.yaw = 32768;
SetBoneRotation('FAN_BONE', rotme, 0, 1);
Super.Tick(DeltaTime);
}
it's not imortant where function called, it anyway doesn't work on client
EvilT-ModZ is offline   Reply With Quote
Old 8th Aug 2011, 01:25 AM   #8
Wormbo
 
 
Wormbo's Avatar
 
Join Date: Jun. 4th, 2001
Location: Germany
Posts: 5,771
Quote:
Originally Posted by EvilT-ModZ View Post
I found that SetBoneRotation not simulated like in ut2003/2004
Code:
native final function SetBoneRotation( name BoneName, optional rotator BoneTurn, optional int Space, optional float Alpha );
so, it's imposible to do bone rotating on client without rewriten class Actor? :/
Native functions are treated like simulated ones. There is no need at all to declare native functions simulated, except maybe to increase the amount of confusion.
Did you make sure the code containing your SetBoneRotation call is executed at all?
__________________
Wormbo's UT/UT2004/UT3 mods | YouTube channel | PlanetJailbreak/JDN | Unreal Wiki | Liandri Archives
Everything you ever wanted to know about replication| UnrealScript security considerations
<elmuerte> you shouldn't do all-nighters, it's a waste of time and effort
<TNSe> nono
<TNSe> its always funny to find code a week later you dont even remember writing
<Pfhoenix> what's worse is when you have a Star Wars moment
<Pfhoenix> "Luke! I am your code!" "No! Impossible! It can't be!"

Last edited by Wormbo; 8th Aug 2011 at 01:27 AM.
Wormbo is offline   Reply With Quote
Old 8th Aug 2011, 01:45 AM   #9
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
Quote:
Originally Posted by Wormbo View Post
Native functions are treated like simulated ones. There is no need at all to declare native functions simulated, except maybe to increase the amount of confusion.
Did you make sure the code containing your SetBoneRotation call is executed at all?
Yes, it's successfully working on single-player game and non-dedicated server
EvilT-ModZ is offline   Reply With Quote
Old 8th Aug 2011, 04:20 AM   #10
EQ²
Code Monkey
 
EQ²'s Avatar
 
Join Date: Oct. 30th, 2004
Location: Near Birmingham, UK
Posts: 243
Quote:
Originally Posted by EvilT-ModZ View Post
Yes, it's successfully working on single-player game and non-dedicated server
I think Wormbo meant "Did you make sure the code containing your SetBoneRotation call is executed at all on the client?". You say your code is called from Tick(), but does the actor have an appropriate RemoteRole which means that Tick() is executed on a client as well? Not all actors do by default so it depends on what the superclass is and whether you've set RemoteRole explicitly: if RemoteRole is ROLE_DumbProxy then that may be your issue.

Also, for performance reasons, sometimes notify functions are explicitly disabled client-side, look for disable('tick'); in superclass definitions to see if tick is being forcibly disabled.

If you want to check whether something is being executed client-side, a quick and dirty way is to deliberately crash the game (logging works too but crashing is quicker ) using:

Code:
simulated function Tick(float DeltaTime)
{
    Super.Tick(DeltaTime);

    if (Level.NetMode != NM_DedicatedServer) // Client or listen server
    {
        // Do some effects stuff

        if (Level.NetMode == NM_Client) // only a client
        {
            assert(false);   // crash the game instantly "assertion failed"
        }
    }
}
If the game crashes then you know it's being executed client-side, if it runs then you know that the function is never being called.
__________________

Before you criticise someone, walk a mile in their shoes; that way, when you criticise them you are a mile away and have their shoes.
EQ² is offline   Reply With Quote
Old 8th Aug 2011, 05:25 AM   #11
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
Quote:
Originally Posted by EQ² View Post
I think Wormbo meant "Did you make sure the code containing your SetBoneRotation call is executed at all on the client?". You say your code is called from Tick(), but does the actor have an appropriate RemoteRole which means that Tick() is executed on a client as well? Not all actors do by default so it depends on what the superclass is and whether you've set RemoteRole explicitly: if RemoteRole is ROLE_DumbProxy then that may be your issue.

Also, for performance reasons, sometimes notify functions are explicitly disabled client-side, look for disable('tick'); in superclass definitions to see if tick is being forcibly disabled.

If you want to check whether something is being executed client-side, a quick and dirty way is to deliberately crash the game (logging works too but crashing is quicker ) using:

Code:
simulated function Tick(float DeltaTime)
{
    Super.Tick(DeltaTime);

    if (Level.NetMode != NM_DedicatedServer) // Client or listen server
    {
        // Do some effects stuff

        if (Level.NetMode == NM_Client) // only a client
        {
            assert(false);   // crash the game instantly "assertion failed"
        }
    }
}
If the game crashes then you know it's being executed client-side, if it runs then you know that the function is never being called.
Ok, game doesn't crash
EvilT-ModZ is offline   Reply With Quote
Old 8th Aug 2011, 06:35 AM   #12
EQ²
Code Monkey
 
EQ²'s Avatar
 
Join Date: Oct. 30th, 2004
Location: Near Birmingham, UK
Posts: 243
Which means your code is never being executed client-side. What is the superclass of the actor this code is inside, and what is the actor's RemoteRole setting?
__________________

Before you criticise someone, walk a mile in their shoes; that way, when you criticise them you are a mile away and have their shoes.
EQ² is offline   Reply With Quote
Old 8th Aug 2011, 07:11 AM   #13
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
Quote:
Originally Posted by EQ² View Post
Which means your code is never being executed client-side. What is the superclass of the actor this code is inside, and what is the actor's RemoteRole setting?
KActor, RemoteRole is ROLE_DumbProxy
EvilT-ModZ is offline   Reply With Quote
Old 8th Aug 2011, 07:47 AM   #14
EQ²
Code Monkey
 
EQ²'s Avatar
 
Join Date: Oct. 30th, 2004
Location: Near Birmingham, UK
Posts: 243
Quote:
Originally Posted by EQ² View Post
if RemoteRole is ROLE_DumbProxy then that may be your issue.
Quote:
Originally Posted by EvilT-ModZ View Post
KActor, RemoteRole is ROLE_DumbProxy
It's unlikely that tick() is being executed client-side then, and since it's KActor you can't replicate functions to it (the actor is not "owned" by a client). Change the RemoteRole to ROLE_SimulatedProxy and see if this cures your problem.

Be aware that changing the RemoteRole can affect other things though so you may need to do some more advanced testing, for example if the superclass' tick() function doesn't check whether it's client side or not then it may be necessary to only call the super.tick() on the 'server', like this:

Code:
simulated function Tick(float DeltaTime)
{
    if (Role == ROLE_Authority) Super.Tick(DeltaTime);

    if (Level.NetMode != NM_DedicatedServer)
    {
        // Do funky client-side stuff
    }
}
Basically this is only an issue if the superclass has been coded with the assumption that certain functions are only executed on the authority, which is pretty messy and stupid but something to be aware of nonetheless.

Another point to note is that having your actor ticked client-side all the time might not be what you really want, for example if the bone rotation effect happens only once you could disable the tick function client-side once the rotation is complete, and re-enable it when needed (for example use a replicated variable and check its value in PostNetReceive.

Code:
var byte ClientEffect, ServerEffect;

replication
{
    unreliable if (Role == ROLE_Authority)
        ServerEffect;
}

simulated function Tick(float DeltaTime)
{
    Super.Tick(DeltaTime);

    if (Level.NetMode != NM_DedicatedServer)
    {
        // Do funky client-side bone rotation

        if (Level.NetMode == NM_Client && SomeVarIndicatesRotationIsFinished)
            disable( 'tick' );
    }
}

// Call this function server-side to trigger client-side effect
function ServerTriggerEffect()
{
    ServerEffect++;
}

simulated function ClientTriggerEffect()
{
    enable( 'tick' );

    // Do stuff
}

simulated event PostNetReceive()
{
    if (Level.NetMode == NM_Client && ClientEffect < ServerEffect)
    {
        ClientTriggerEffect();
    }

    ClientEffect = ServerEffect;
}

defaultproperties
{
    bNetNotify=true  // Enables the PostNetReceive event
}
Notice that this example only disables the tick event on clients (not servers, single player, or listen server). In reality if the event happens once and never again you can disable tick client-side after your bone rotation has played and not worry about re-enabling it. Conversely, if your effect happens at some arbitrary time after the actor is spawned then you should disable tick in PreBeginPlay (on client) and enable it with a replicated variable as shown when needed.
__________________

Before you criticise someone, walk a mile in their shoes; that way, when you criticise them you are a mile away and have their shoes.

Last edited by EQ²; 8th Aug 2011 at 07:50 AM.
EQ² is offline   Reply With Quote
Old 8th Aug 2011, 09:32 AM   #15
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
Quote:
Originally Posted by EQ² View Post
Be aware that changing the RemoteRole can affect other things though so you may need to do some more advanced testing, for example if the superclass' tick() function doesn't check whether it's client side or not then it may be necessary to only call the super.tick() on the 'server', like this:
Second code will be affected without ROLE_SimulatedProxy?
Because actor with simulatedproxy have collapsed on client

And "bNetNotify" not written on game's class Actor

Last edited by EvilT-ModZ; 8th Aug 2011 at 09:36 AM.
EvilT-ModZ is offline   Reply With Quote
Old 8th Aug 2011, 09:45 AM   #16
EQ²
Code Monkey
 
EQ²'s Avatar
 
Join Date: Oct. 30th, 2004
Location: Near Birmingham, UK
Posts: 243
Please elaborate? Are you saying that changing it to SimulatedProxy causes the physics to fail client-side? If that's the case then you may have to do the rotation with a "helper" actor. Basically this would be another replicated actor which actually manages the effects for the KActor and can safely be set to SimulatedProxy to run the code you need.
__________________

Before you criticise someone, walk a mile in their shoes; that way, when you criticise them you are a mile away and have their shoes.
EQ² is offline   Reply With Quote
Old 8th Aug 2011, 10:03 AM   #17
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
Quote:
Originally Posted by EQ² View Post
Please elaborate? Are you saying that changing it to SimulatedProxy causes the physics to fail client-side? If that's the case then you may have to do the rotation with a "helper" actor. Basically this would be another replicated actor which actually manages the effects for the KActor and can safely be set to SimulatedProxy to run the code you need.
So, im sure what bone rotating working with simulatedproxy, but
http://s55.radikal.ru/i149/1108/dd/d343e374a968.jpg, you can see:
rendering mesh of actor stay static and it's collision and some stuff have moved
EvilT-ModZ is offline   Reply With Quote
Old 10th Aug 2011, 09:00 AM   #18
EQ²
Code Monkey
 
EQ²'s Avatar
 
Join Date: Oct. 30th, 2004
Location: Near Birmingham, UK
Posts: 243
If making it SimulatedProxy breaks it client-side then you'll have to stick with dumb proxy - this is likely either because some code isn't checking whether Role == Authority and is executing client-side with empty values, or because setting it to SimulatedProxy alters the physics behaviour, either way you need to find another solution.

If your actor has other attached actors you might be able to put your code in them, either that or just make your own attached "helper" actor to just provide the animation. Here's a canned example (pseudocode, I'm typing directly into the edit window not into a nice IDE):

Your helper actor:
Code:
class BoneRotationHelper extends Actor notplaceable;

var float currentBoneRotation, desiredBoneRotation, boneRotationRate;
var name boneName;

simulated event PreBeginPlay()
{
    currentBoneRotation = 0;
    disable( 'tick' );
}

// Call this function to begin rotating the specified bone at the specifed rate
simulated function RotateBone(name boneToRotate, float desiredPitch, float desiredRate)
{
    currentBoneRotation = MyKActor(Owner).GetBoneRotation( boneToRotate ).Pitch;
    desiredBoneRotation = desiredPitch;
    boneRotationRate = desiredRate;
    boneName = boneToRotate;
    enable( 'tick' );
}

simulated event Tick(float DeltaTime)
{
    local Rotator boneRotation;
    local float deltaPitch;

    Super.Tick(DeltaTime);

    if (currentBoneRotation < desiredBoneRotation)
        deltaPitch = boneRotationRate * DeltaTime;
    else if (currentBoneRotation > desiredBoneRotation)
        deltaPitch = -boneRotationRate * DeltaTime;
    else
        disable( 'tick' );   // Target reached, disable ticking
  
    currentBoneRotation += deltaPitch
    boneRotation.Pitch = currentBoneRotation;

    MyKActor(Owner).SetBoneDirection( boneName, boneRotation );
}

defaultproperties
{
    RemoteRole=ROLE_None
}
Your KActor derived class
Code:
class MyKActor extends KActor placeable;

var BoneRotationHelper rotationHelper;
var byte serverEffect, clientEffect;

replication
{
    reliable if (Role == ROLE_Authority)
        serverEffect;
}

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

    // Only need the helper on client, listen server and SP
    if (Level.NetMode != NM_DedicatedServer)
    {
        rotationHelper = Spawn( class'BoneRotationHelper' );
    }
}

simulated event PostNetBeginPlay()
{
    Super.PostNetBeginPlay();

    // Initial replication, set effect counter to avoid triggering
    // effect when actor becomes relevant
    clientEffect = serverEffect;
}

simulated event Destroyed()
{
    // Clean up the helper when we are destroyed
    if (rotationHelper != None)
    {
        rotationHelper.Destroy();
        rotationHelper = None;
    }
}

// Call this function server-side to trigger the effect, client replication
// is handled by the replicated variable
function TriggerEffect()
{
    serverEffect++;
    ClientTriggerEffect();    // Trigger event on listen server / single player
}

simulated function ClientTriggerEffect()
{
    if (Level.NetMode != NM_DedicatedServer && rotationHelper != None)
    {
        rotationHelper.RotateBone( 'someBone', 16384, 600 );
    }
}

simulated event PostNetReceive()
{
    if (Role < ROLE_Authority && serverEffect > clientEffect)
    {
        clientEffect = serverEffect;
        ClientTriggerEffect();
    }
}

defaultproperties
{
    RemoteRole = ROLE_DumbProxy
    bNetNotify = true
}
Notice that RemoteRole on the helper actor is ROLE_None, this means the actor isn't replicated, instead a separate copy is spawned by the client and the server and the replication of the effect (the bone rotation) is still handled on your main KActor.

The example also disables ticking the helper actor when it is not doing any work, this isn't strictly necessary but a useful optimisation in case you have lots of these.

You should also note that since we're spawning a new actor we have to manage cleaning it up ourselves, this is managed in the KActor's Destroyed() function.

This is just a canned example really but hopefully it helps, sorry if the code doesn't compile but I don't have UT2k4 or an IDE here at work so I've just bashed this out from memory.
__________________

Before you criticise someone, walk a mile in their shoes; that way, when you criticise them you are a mile away and have their shoes.
EQ² is offline   Reply With Quote
Old 11th Aug 2011, 07:26 AM   #19
EvilT-ModZ
Un-Gravitify
 
EvilT-ModZ's Avatar
 
Join Date: Aug. 3rd, 2011
Location: Russia
Posts: 36
Quote:
Originally Posted by EQ² View Post
bNetNotify = true
I have a problem, game's class "Actor" doesn't have this bool,
it will be working without it?
EvilT-ModZ is offline   Reply With Quote
Old 11th Aug 2011, 05:07 PM   #20
EQ²
Code Monkey
 
EQ²'s Avatar
 
Join Date: Oct. 30th, 2004
Location: Near Birmingham, UK
Posts: 243
Afraid not, it looks like they took that function out in the Postal2 build of UE2 (it's not uncommon for licensees to remove functions they don't need and I don't think multiplayer was thought about. Basically you can't use the method above by the looks of it.

So, you can't make it simulatedproxy and you can't do efficient replication on the actor so you'll have to attach the helper actor server-side and do your replication in there. The down side is that because you can't use PostNetReceive you'll have to tick the helper actor all the time and check the value of your replication flag every tick. It sucks and but I can't see there's much alternative really.
__________________

Before you criticise someone, walk a mile in their shoes; that way, when you criticise them you are a mile away and have their shoes.
EQ² is offline   Reply With Quote
Reply

Tags
bone, boning, postal 2, rotating

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 02:39 PM.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.

Copyright ©1998 - 2012, BeyondUnreal, Inc.
Privacy Policy | Terms of Use
Bandwidth provided by AtomicGamer