News UnrealEd Files Mods FragBU Liandri Archives
BeyondUnreal Forums

Go Back   BeyondUnreal Forums > Unreal Development > Coding

Reply
 
Thread Tools Display Modes
Old 16th Sep 2003, 01:23 PM   #1
jb
Registered User
 
Join Date: May. 22nd, 2000
Posts: 278
Unhappy Replication Issue on Melee Weapons

Folks,

me again with YAI (yet another issue) that I have not been able to wrap my arms fully around to and could use a kick in the right direction. It involves melee combat and on-line games. What we did is something a bit different. We got away from using the trace X units in front of a player and went to an animation driven system. We created a dozen or so custom attack animations for the pawn class( one handed swings, two handed, jabs/pokes, ect). We look at your movement and the base the attack animation on the movement. The key is the weapon and how its attached. We use one standard bone in the model to attach to your hand. Then we placed 2 bones in the model of the weapon. We place one of them at the tip of the blade and the other in the hilt of a sword (for example). Then we the player "fires" the weapon, we start tracing between these two points. As soon something breaks that trace we look at the hit detection to see if it was a "wall", a player or another weapon (ie a block) then handle that hit. The system works pretty well off-line. However on-line its a different story and I am sure its how I set up the replication of the weapons. Instead of using a started weapon attachment I used this:

[code]
//==================================================================
// The active weapon file
//==================================================================

class swordAttachmentb extends MeleeWeapon placeable;

var ShieldSparks Sparks;
var(Health) float Health;

var() int MomentumTransfer;
var() float damMomentum; // changed type to float from int -jm
var() int Damage;
var() int DamageRadius;
var() int DamageType;
var swipetrail SweepTrail;
var() float HeadShotDamageMult;
var() float HeadShotRadius;
var name ActionAttack;
var array<Actor> HitActors[16]; // this array will keep our list of hit actors.
// Sounds vars
var(MeleeSounds) array<Sound> BlockSound;
var(MeleeSounds) array<Sound> Melee_HitFlesh;
var(MeleeSounds) array<Sound> Melee_HitArmor;
var(MeleeSounds) array<Sound> Head_Shot;
var Sound HitWallSound;


//=============================================================================
// PostBeginPlay
// Set up the swipe effects
//=============================================================================
simulated function PostBeginPlay()
{
local actor W;
W = self;
// log("I am here " @location);
//Log("My instigator is " @instigator.controller.Playerreplicationinfo.PlayerName);
if ( Level.NetMode != NM_DedicatedServer)
{
if (!Level.bDropDetail && (Level.DetailMode != DM_Low) )
SweepTrail = Spawn(class 'swipetrail', self);
if ( SweepTrail != None )
{
W.AttachToBone(SweepTrail, 'sweepjoint3');
SweepTrail.mRegen =false;
}
}
}


//=============================================================================
// ThirdPersonEffects
// Blank out any current 3rd person effects
//=============================================================================
simulated event ThirdPersonEffects()
{
}


//=============================================================================
// Explode
// Blows up with an effect?
// Jb: Why? for like a shattered sword???? Hmm Come back and remove later?
//=============================================================================
simulated function Explode(vector HitLocation, vector HitNormal)
{ // is this used? - JM
if (Role == ROLE_Authority)
{
// HurtRadius(Damage, DamageRadius, class'ketoweapons.DamTypesever',
// MomentumTransfer, HitLocation );
}
if (EffectIsRelevant(Location, false))
Spawn(class 'ImpactDust',,, Location); // ,rotator(Velocity));
}


//=============================================================================
// Destroyed
// Remove the swipe/sparks effect
//=============================================================================
simulated function Destroyed()
{
if (SweepTrail != None)
sweeptrail.Destroy();
if (Sparks != None)
Sparks.Destroy();
Super.Destroyed();
}


//=============================================================================
// CheckHit
// Remove the swipe/sparks effect
//=============================================================================
function bool CheckHit(Actor A)
{
local int i;

// Check if this actor is valid to be struck
if(A == Owner || A.Owner == Owner || A == self)
{
return false;
}
// Check this actor against the HitCount array
for(i = 0; i < 16; i++)
{
if(HitActors[i]== A)
{ // Found this actor in the list
return false;
}
}
// The actor wasn't in the list, so add it
for(i = 0; i < 16; i++)
{
if(HitActors[i] == None)
{
HitActors[i]= A;
return true;
}
}
return(false);
}


//=============================================================================
// ClearHitActors
// Resets the array of actors we hit
//=============================================================================
function ClearHitActors()
{
local int i;
for(i = 0; i < 16; i++)
HitActors[i] = None;

}


//=============================================================================
// Timer
// This function checks to see if any object passes between the sweep joints of
// the weapon.
//
// Jb: AdHOCK (or is that AdHACK...hehheh get it...hahaha) fix was to move it to a timer and have the
// fire class controlls when the timer as active and not active....hey its a bit better...
//=============================================================================
Function Timer()
{
local vector newpos1;
local vector newpos2;
local coords newcoords1;
local coords newcoords2;
local Vector End, HitLocation, HitNormal, Start;
local actor Other;
local actor W;
// local xWeaponAttachment WeaponAttachment;
local Weapon Weapon;
local Controller C;

if (SweepTrail != None)
SweepTrail.mRegen = true;

W = self; // say my name...
newcoords1 = W.GetBoneCoords('sweepjoint1'); // get the location of the sword blade start
newcoords2 = W.GetBoneCoords('sweepjoint2'); // get the location of the sword blade end
newpos1 = newcoords1.Origin;
newpos2 = newcoords2.Origin;
log("sweep joints are at " @newpos1 @newpos2);
MeleePawn(Instigator).pt1 = newcoords1.Origin;
MeleePawn(Instigator).pt2 = newcoords2.Origin; // copy for async trace drawing

Start = newpos1;
End = newpos2;
Other = Trace(HitLocation, HitNormal, End, Start, true); // see if the sword 'line' hits anything
C = Instigator.Controller;
Weapon = Instigator.Weapon;

if (Other != None && Other != W )
{
if (Other.IsA('MeleeWeapon'))
{
PlaySound(BlockSound[Rand(BlockSound.Length)], SLOT_Interact);
if (CheckHit(Other))
{
// Hit a new object here..spawn effect
Spawn(class 'WallSparks',,, HitLocation);
}

// We also should stop our swing...as we are not swining amy more.
// Cad do this by setting the bfire tag to false, then play another
// animation to stop

// Jb: Stop their fire
if (C != none)
{
C.bFire = 0;
Weapon.StopFire(0); // now we need to stop the player from holding the firebutton down
}
// Reset thier animation
ActionAttack = '2hstance';
MeleePawn(Instigator).SetAnimAction(ActionAttack);
SwordFire(Weapon.FireMode[0]).GotoState(''); // Stop the swing!
// moved gotostate to the end, in case it was jumpin early. -jm
}
else if (Other.bWorldGeometry)
{
// weve struck map stuff
PlaySound(HItWallSound, SLOT_Interact);
if (CheckHit(Other))
{

Spawn(class'HitEffect'.static.GetHitEffect(Other, Other.Location,HitNormal)
,,, HitLocation, Rotator(HitNormal));

}
if (C != none)
{
C.bFire = 0;
Weapon.StopFire(0); // now we need to stop the player from holding the firebutton down
}
// Reset their animation
ActionAttack = '2hstance';
MeleePawn(Instigator).SetAnimAction(ActionAttack);
// on the surface type (like rune did)
SwordFire(Weapon.FireMode[0]).GotoState(''); // Stop the swing!
}
else if (Other.IsA('Projectile'))
{
// Maybe play a custom sound for projectiles here??
// call that projeciles ProcessTouch to see if it can be refelected
Projectile(Other).ProcessTouch(Instigator, HitLocation);
}
else if (!Other.bWorldGeometry && Other != Instigator && Other != Owner && Other.IsA('Pawn'))
{
// we hit paydirt! err, it hit the other pawn in the flesh, time to do some damage.
// Jb: Maybe put a check for a team mate and if so stop the swing or damage?

//Play sounds here
if (Pawn(Other).ShieldStrength != 0.0)
PlaySound(Melee_HitArmor[Rand(Melee_HitArmor.Length)], SLOT_Interact); // implies hit a target with shield/armor
else
PlaySound(Melee_HitFlesh[Rand(Melee_HitFlesh.Length)], SLOT_Interact); // implies hit a target with w/o shield/armor
// give them damage
ProcessTouch(Other, HitLocation);
}

}

// else
// {
if (SweepTrail != None)
SweepTrail.mRegen = false;
// }
}


//=============================================================================
// ProcessTouch
// Call when we hit another actor to see if we should hand out damage.
//=============================================================================
simulated function ProcessTouch(Actor Other, Vector hitLocation)
{
local Vector X, moe;
local float dist;
local class<DamageType> swordDamageType;

if (Other == Instigator)
return;
if (Other == Owner)
return;
if (Other == self)
return;

Damage = Default.Damage + (5*Sword(Instigator.Weapon).CurrentStance);

// if the current pawn is in berserk mode, increase their damage by 20%
if ( Instigator.IsA('xPawn') && xPawn(Instigator).CurrentCombo != none && xPawn(Instigator).CurrentCombo.IsA('ComboBerserk'))
Damage += Damage * 0.20;

if (Other != None && Other.IsA('xPawn') )
{
X = Normal(Other.Location-Instigator.location);
moe = (X+vect(0,0,0.5))*damMomentum;
// collect damagetype from custom weapons
if ( Instigator.Weapon.IsA( 'Sword' ) )
swordDamageType = class 'DamTypeSword';
else if ( Instigator.Weapon.IsA( 'Axe' ) )
swordDamageType = class 'DamTypeAxe';
else
swordDamageType = class 'DamTypeDoubleAxe';

if (Pawn(Other) != None)
{
if (Other.GetClosestBone(HitLocation, X, dist, 'head', HeadShotRadius) == 'head')
{
PlaySound(Head_Shot[Rand(Head_Shot.Length)], SLOT_Interact);
Other.TakeDamage(Damage * HeadShotDamageMult,Instigator, HitLocation, moe, class 'Melee.DamTypeseverHead ');
}
else
{
Other.TakeDamage(Damage, Instigator, HitLocation, moe, swordDamageType );
}
}
}
else if (Other != None && Other.bProjTarget)
{
Other.TakeDamage(Damage, Instigator, HitLocation, moe, swordDamageType );
// Need a sound for a reflect/projectile hit?? Or No solid hits?
PlaySound(HitWallSound, SLOT_Misc);
}
}



defaultproperties
{
Health=500;
MomentumTransfer=30000;
damMomentum=25000f;
HeadShotDamageMult=2.000000;
HeadShotRadius=8.000000;
Damage=15;
DamageRadius=45;
DrawType=DT_Mesh;
// Temp add by Jb
Mesh=SkeletalMesh'Chaos_melee1.OldBastardSword'
DrawScale=0.425
// end temp
SurfaceType=EST_Metal;
SoundRadius=100.000000;
SoundVolume=255;
TransientSoundVolume=1.200000;
TransientSoundRadius=400.000000;
bCollideActors=True;
bCollideWorld=True;
bBlockActors=True;
bBlockPlayers=True;
// added in these to better model the sword
CollisionRadius=6;
CollisionHeight=41;
BlockSound(0)=Sound'MeleeSounds.Melee.sword_blockmelee1'
BlockSound(1)=Sound'MeleeSounds.Melee.sword_blockmelee2'
BlockSound(2)=Sound'MeleeSounds.Melee.sword_blockmelee3'
BlockSound(3)=Sound'MeleeSounds.Melee.sword_blockmelee4'
BlockSound(4)=Sound'MeleeSounds.Melee.sword_blockmelee6'
BlockSound(5)=Sound'MeleeSounds.Melee.sword_blockmelee5'
HitWallSound=Sound'MeleeSounds.Melee.sword_wall1'
Melee_HitFlesh(0)=Sound'MeleeSounds.Melee.melee_hitflesh1'
Melee_HitFlesh(1)=Sound'MeleeSounds.Melee.melee_hitflesh2'
Melee_HitFlesh(2)=Sound'MeleeSounds.Melee.melee_hitflesh3'
Melee_HitFlesh(3)=Sound'MeleeSounds.Melee.melee_hitflesh4'
Melee_HitFlesh(4)=Sound'MeleeSounds.Melee.melee_hitflesh5'
Melee_HitFlesh(5)=Sound'MeleeSounds.Melee.melee_hitflesh6'
Melee_HitFlesh(6)=Sound'MeleeSounds.Melee.melee_hitflesh7'
Melee_HitFlesh(7)=Sound'MeleeSounds.Melee.melee_hitflesh8'
Melee_HitArmor(0)=Sound'MeleeSounds.Melee.melee_hitarmor1'
Melee_HitArmor(1)=Sound'MeleeSounds.Melee.melee_hitarmor2'
Melee_HitArmor(2)=Sound'MeleeSounds.Melee.melee_hitarmor3'
Melee_HitArmor(3)=Sound'MeleeSounds.Melee.melee_hitarmor4'
Melee_HitArmor(4)=Sound'MeleeSounds.Melee.melee_hitarmor5'
Melee_HitArmor(5)=Sound'MeleeSounds.Melee.melee_hitarmor6'
Head_Shot(0)=Sound'MeleeSounds.Melee.melee_headshot1'
Head_Shot(1)=Sound'MeleeSounds.Melee.melee_headshot2'
Head_Shot(2)=Sound'MeleeSounds.Melee.melee_headshot3'
Head_Shot(3)=Sound'MeleeSounds.Melee.melee_headshot4'
Head_Shot(4)=Sound'MeleeSounds.Melee.melee_headshot5'
}

and its partent:

Code:
//============================================================
// base class for the weapon "attachments"
//============================================================
class MeleeWeapon extends Actor;

defaultproperties
{

    bCollideActors=True;
    bCollideWorld=True;
    bBlockActors=True;
    bBlockPlayers = true;
    bPathColliding = False;

    //Replication stuff
    bGameRelevant=True;
    bAlwaysRelevant=True
   //bReplicateMovement=false
}

No real reason why I chose to make this a parent of Actor. What should I have used for the parent of the MeleeWeapon Class? So in on-line games it does not do any damage. And some time the sword will attach it self to the players hands. It depends on the bReplicateMovement var. If I leave it in as false, then my sword attachment spawns but its is never attached to my hand. Thus I walk around with out a weapon. If I remove it (so its set to true via the Actor class setting) then my weapon gets attached. However when I log the location of the trace joints they never move. So I can not hit anything. Now with some work I was able to play on-line with the bots. I noticed that when the swords did not attach (ie bReplicateMovement=false) I would see these swords lying at their spawns. If I walked up to a bots sword and that bot swung, then I DID TAKE damage. So the method will work. Once I can figure out what I did wrong. I guess I don't understand how it can attach the weapon and yet not have the sword joints be updated. Any thoughts???
__________________
Jb
ChaosUT

Last edited by jb; 16th Sep 2003 at 01:25 PM.
jb is offline   Reply With Quote
Old 16th Sep 2003, 03:00 PM   #2
Daid303
MSPA
 
Join Date: Aug. 7th, 2002
Location: The Netherlands (yes, that's Holland)
Posts: 246
Why not use InventoryAttachment as base class?
Daid303 is offline   Reply With Quote
Old 16th Sep 2003, 04:34 PM   #3
jb
Registered User
 
Join Date: May. 22nd, 2000
Posts: 278
Daid303,

ok that makes a lot of senses. I made that change but I still do not get any updates to the postion of the sword when I log its location:

Code:
      log("my postion is " @self.location);
      log("sweep joints are at " @newpos1 @newpos2);
These never change in value even though the sword is in my hand and moving. Now in an off-line game these change. Any ideas what I did wrong?
__________________
Jb
ChaosUT
jb is offline   Reply With Quote
Old 17th Sep 2003, 08:26 AM   #4
RegularX
Master of Dagoth Lies
 
RegularX's Avatar
 
Join Date: Feb. 2nd, 2000
Location: Chicago, IL
Posts: 1,215
What if you keep InventoryAttachment as the parent but change "bFastAttachmentReplication" to be false? It might be setting the Actor mostly correct, but I wonder if that var isn't telling the native replication to not worry about sending the location/rotation over the wire.
__________________
_____________________________
I remember old school.

Champion of Glaucoma Inducing Radiation Everywhere
RegularX is offline   Reply With Quote
Old 17th Sep 2003, 09:31 AM   #5
jb
Registered User
 
Join Date: May. 22nd, 2000
Posts: 278
RegX,

thanks for the reply. Last night I tried a few things and one of them was as you suggested as well as the bOnlyDirtyReplication. Still no luck. At this point i have no idea why I can see the sword in the hands of my players yet logs show it never moves eventhough I go through the level hopping like a bunny. I would expect if the log is showing it not moving then it would not be attached. Confusing
__________________
Jb
ChaosUT
jb is offline   Reply With Quote
Old 17th Sep 2003, 09:35 AM   #6
RegularX
Master of Dagoth Lies
 
RegularX's Avatar
 
Join Date: Feb. 2nd, 2000
Location: Chicago, IL
Posts: 1,215
self.location doesn't change, but it's also not 0,0,0 ?
__________________
_____________________________
I remember old school.

Champion of Glaucoma Inducing Radiation Everywhere
RegularX is offline   Reply With Quote
Old 17th Sep 2003, 09:46 AM   #7
jb
Registered User
 
Join Date: May. 22nd, 2000
Posts: 278
Yeap its set to some non-zero value that I am almost sure its the spawn point of my player (or close to it).

I tried a rather nasty hack of settibg its location every tick to my instigators location. Well I got the logs to show that it moved. However it detached from my hand. I did not figure on a way to reattach it so dropped that idea. Thanks again!
__________________
Jb
ChaosUT
jb is offline   Reply With Quote
Old 17th Sep 2003, 09:50 AM   #8
RegularX
Master of Dagoth Lies
 
RegularX's Avatar
 
Join Date: Feb. 2nd, 2000
Location: Chicago, IL
Posts: 1,215
This is totally a side note - but is it me, or are semicolons suddenly OK in default props? didn't that use to hose the whole section?
__________________
_____________________________
I remember old school.

Champion of Glaucoma Inducing Radiation Everywhere
RegularX is offline   Reply With Quote
Old 17th Sep 2003, 09:51 AM   #9
jb
Registered User
 
Join Date: May. 22nd, 2000
Posts: 278
Well I am lazy and will remove them all. Normally spaces are bad in the default section unless you use a semicolon
__________________
Jb
ChaosUT
jb is offline   Reply With Quote
Old 17th Sep 2003, 10:08 AM   #10
RegularX
Master of Dagoth Lies
 
RegularX's Avatar
 
Join Date: Feb. 2nd, 2000
Location: Chicago, IL
Posts: 1,215
Doing a bit reading, it seems like Role_DumbProxy would be a better choice unless the Owner is acting like a base. ROLE_SimulatedProxy (in inventory attachment) won't replication location if there's no base.

If it is the base, try keeping SimulatedProxy and setting bUpdateSimulatedPosition=True ... (at this point I'm just trying to decipher Actor's replication rules for location)
__________________
_____________________________
I remember old school.

Champion of Glaucoma Inducing Radiation Everywhere
RegularX is offline   Reply With Quote
Old 17th Sep 2003, 01:38 PM   #11
jb
Registered User
 
Join Date: May. 22nd, 2000
Posts: 278
Thanks I will try that as well as do some more reading on this as well.
__________________
Jb
ChaosUT
jb is offline   Reply With Quote
Old 17th Sep 2003, 05:27 PM   #12
jb
Registered User
 
Join Date: May. 22nd, 2000
Posts: 278
Reg,

thanks again but still the same results no mater what I try to set its role too....
__________________
Jb
ChaosUT
jb is offline   Reply With Quote
Old 20th Sep 2003, 06:50 AM   #13
jb
Registered User
 
Join Date: May. 22nd, 2000
Posts: 278
Update:

Erik from Epic replied with this:

Quote:
> Bone positions are not replicated directly, what's more they're not
> updated at all if the base mesh is not rendered - like on a server or
> even on a client PC when the mesh is outside the field of view.
> Except that is, if any game code explicitly requests a bone position
> (GetBonePosition/Rotation etc) which causes the bones to be updated
> internally.
>
> - Erik
For me I logged the bone postion of the right hand. That showed up and had real data on server. It also moved. So now that I know I can use the location of the righthand on the server, it should be a simple matter of calculating those sweep joints with some vector math.
__________________
Jb
ChaosUT
jb is offline   Reply With Quote
Old 23rd Sep 2003, 07:14 PM   #14
DannyMeister
UT3 Jailbreak Coder
 
DannyMeister's Avatar
 
Join Date: Dec. 11th, 2002
Location: Bolivar, Missouri
Posts: 1,238
Wrap long lines of code, pretty please!

__________________

UT3 Jailbreak is under development! Forums | Website
DannyMeister is offline   Reply With Quote
Old 6th Oct 2003, 09:06 AM   #15
jb
Registered User
 
Join Date: May. 22nd, 2000
Posts: 278
Found a hint burried in the UTMod List.

Basically what I had to do was get the bone cord of the players hands. Move the Attachment class to that location. Set the rotation of the attachment class to that of the right hand. Then reattach. Just 6 lines of code is all it took
__________________
Jb
ChaosUT

Last edited by jb; 6th Oct 2003 at 09:10 AM.
jb is offline   Reply With Quote
Reply

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 05:34 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