PDA

View Full Version : Lava Caster - SubClasses


ROFL 451
11th Mar 2004, 10:15 PM
Ok, the Lava Caster is a child of the Bio-Rifle

Does this mean that for every category (DamTypeBioGlob, BioAmmoPickup, etc) I need to have a subclass?

So for my Lava Caster Pickup it needs to be

class LavaCasterPickup extends class BioRiflePickup

or my DamTypeLavaGlob needs to be

class damtypelavaglob extends class damtypebioglob

and so forth? Lemme post some of my code.
This is the DamTypeLavaGlob code

class DamTypeLavaGlob extends DamTypeBioGlob
abstract;

defaultproperties
{
DeathString="%o was ignited by %k's Lava Caster."
MaleSuicide="%o was terminated by his own lava."
FemaleSuicide="%o was terminated by her own lava."

WeaponClass=class'LavaCaster'

bDetonatesgoop=true
bDelayedDamage=true
}


This is the LavaAmmo

class LavaAmmo extends BioAmmo;

defaultproperties
{
ItemName="Lava Caster Ammo"
IconMaterial=Material'InterfaceContent.Hud.SkinA'
IconCoords=(X1=545,Y1=75,X2=644,Y2=149)

PickupClass=class'LavaAmmoPickup'
MaxAmmo=30
InitialAmount=10
}


This is the LavaAmmoPickup

class LavaAmmoPickup extends BioAmmoPickup;

#exec OBJ LOAD FILE=PickupSounds.uax

defaultproperties
{
InventoryType=class'LavaAmmo'

PickupMessage="You picked up some Lava Caster ammo"
PickupSound=Sound'PickupSounds.FlakAmmoPickup'
PickupForce="FlakAmmoPickup" // jdf

AmmoAmount=15

StaticMesh=StaticMesh'XXXXXXX'
DrawType=DT_StaticMesh
}


This is the LavaCasterPickup code

class LavaCasterPickup extends BioRiflePickup;

defaultproperties
{
InventoryType=class'LavaCaster'

PickupMessage="You got the Lava Caster"
PickupSound=Sound'PickupSounds.FlakCannonPickup'
PickupForce="FlakCannonPickup" // jdf

MaxDesireability=+0.75

StaticMesh=StaticMesh'XXXXXX'
DrawType=DT_StaticMesh
DrawScale=0.7
}

This is my AltFireSmallLavaGlob code

class LavaSmallProj extends BioGlob;

defaultproperties
{
Skins(0)=Texture'H_E_L_Ltx.Shaders.cp_lava2_epic'
DrawScale=0.7
Damage=33.0
DamageRadius=180.0
MomentumTransfer=40000
MyDamageType=class'DamTypeLavaGlob'
}


Wherever there is "XXXXXX" that means I don't have that package yet. Could you guys check my code for blatant errors, please?

Edit: Also, what do I need to code to make the glob burn you even after you leave it's area?

#2. How do I make it skeletize people when they die from being killed with the Lava Caster?

Donator
12th Mar 2004, 03:20 AM
1) You don't have to.

General idea of subclasses:

You (or some nice guy at Epic) defined a master class, like "Object", or "Actor", that has certain properties like mass, speed, size, display type and so on, those variables can be changed under defaultproperies. Now "Inventory" is a subclass of "Actor", which means it has all the properties of "Actor" like mass, speed, size, whatever, but has the added ability of being carried around by other Actors. Next step, "Weapon" is a subclass of "Inventory", you guess it: it can be carried around, holds all the general properties of Actor and has even more complex abilities like firing and reloading. Basically the defaultproperties list grows on and on, you could subclass your new weapon directly from "Actor", but then you would have to set every variable found in the defaultproperties list of Actor, Inventory and Weapon, which would make a VERY long list. The general idea is not having to repeat hundreds of lines of code over and over even though they'd be the same in all subclasses anyway.

Another thing: Variable settings in subclasses override those in their superclasses: you can make a subclass of BioRifle, but use a different model or skin nevertheless.

2) For a continuous damage, it's easiest to spawn an invisible actor, attach (SetBase) it to the target, call a timer function from PostNetBeginPlay in that actor and write a HurtRadius command in that timer.

you will likely put that into a DelayedHurtRadius function:

foreach DynamicActors( class'TheDamageActor', P )
{
if ( P.Base == Victims )
P.Destroy();
}
//<-the above lines will remove an old damage actor before a new one is atached
P = Spawn(Class'TheDamageActor',Instigator,,HitLocation);
P.SetBase(Victims);


and this is an example of how such a damage actor might look like:

class TheDamageActor extends Actor;

simulated function PostBeginPlay()
{
SetTimer( 3.0, true );
}

simulated function Timer()
{
if ( xPawn(Base) != None && xPawn(Base).Health > 0 )
{
Base.TakeDamage(5,Instigator,Location,vect(0,0,0),Class'MyDamType');
}
else
Destroy();
}


defaultproperties
{
Physics=10
DrawType=0
bHidden=True
LifeSpan=12;
}

<- this will hurt you for 5 points every 3 seconds, after 12 seconds the actor will auto destroy


3) Skeletizing is very easy, just add bSkeletize=True in the defaultproperties of your damage type.

Postal
12th Mar 2004, 10:25 AM
Donator, you hit the nail on the head.

ROFL 451
12th Mar 2004, 01:57 PM
Ok, I was trying to complile just edited Bio-Rifle code today, and I have everything specified LavaCaster, exept where the Bio Rifle mesh is needed and so forth. BUT! I do a ucc make and i get an error with one of my .uc packages. Here is code:

LavaGlob code

class LavaGlob extends Projectile;

var xEmitter Trail;
var() int BaseDamage;
var() float GloblingSpeed;
var() float RestTime;
var() float TouchDetonationDelay; // gives player a split second to jump to gain extra momentum from blast
var() bool bMergeGlobs;
var() float DripTime;
var() int MaxGoopLevel;

var int GoopLevel;
var float GoopVolume;
var Vector SurfaceNormal;
var bool bCheckedSurface;
var int Rand3;
var bool bDrip;
var bool bNoFX;
var bool bOnMover;

var() Sound ExplodeSound;
var AvoidMarker Fear;

replication
{
reliable if (bNetInitial && Role == ROLE_Authority)
Rand3;
}

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

SetOwner(None);

LoopAnim('flying', 1.0);

if (Role == ROLE_Authority)
{
Velocity = Vector(Rotation) * Speed;
Velocity.Z += TossZ;
}

if (Role == ROLE_Authority)
Rand3 = Rand(3);
if ( Level.bDropDetail )
{
bDynamicLight = false;
LightType = LT_None;
}
if ( Instigator != None )
InstigatorController = Instigator.Controller;
}

simulated function PostNetBeginPlay()
{
if (Role < ROLE_Authority && Physics == PHYS_None)
{
Landed(Vector(Rotation));
}
}

simulated function Destroyed()
{
if ( !bNoFX && EffectIsRelevant(Location,false) )
{
Spawn(class'xEffects.GoopSmoke');
Spawn(class'xEffects.GoopSparks');
}
if ( Fear != None )
Fear.Destroy();
if (Trail != None)
Trail.Destroy();
Super.Destroyed();
}

simulated function MergeWithGlob(int AdditionalGoopLevel)
{
}

auto state Flying
{
simulated function Landed( Vector HitNormal )
{
local Rotator NewRot;
local int CoreGoopLevel;

if ( Level.NetMode != NM_DedicatedServer )
{
PlaySound(ImpactSound, SLOT_Misc);
// explosion effects
}

SurfaceNormal = HitNormal;

// spawn globlings
CoreGoopLevel = Rand3 + MaxGoopLevel - 3;
if (GoopLevel > CoreGoopLevel)
{
if (Role == ROLE_Authority)
SplashGlobs(GoopLevel - CoreGoopLevel);
SetGoopLevel(CoreGoopLevel);
}
spawn(class'BioDecal',,,, rotator(-HitNormal));

bCollideWorld = false;
SetCollisionSize(GoopVolume*10.0, GoopVolume*10.0);
bProjTarget = true;

NewRot = Rotator(HitNormal);
NewRot.Roll += 32768;
SetRotation(NewRot);
SetPhysics(PHYS_None);
bCheckedsurface = false;
Fear = Spawn(class'AvoidMarker');
GotoState('OnGround');
}

simulated function HitWall( Vector HitNormal, Actor Wall )
{
Landed(HitNormal);
if (Mover(Wall) != None)
{
bOnMover = true;
SetBase(Wall);
if (Base == None)
BlowUp(Location);
}
}

simulated function ProcessTouch(Actor Other, Vector HitLocation)
{
local BioGlob Glob;

Glob = BioGlob(Other);

if ( Glob != None )
{
if (Glob.Owner == None || (Glob.Owner != Owner && Glob.Owner != self))
{
if (bMergeGlobs)
{
Glob.MergeWithGlob(GoopLevel); // balancing on the brink of infinite recursion
bNoFX = true;
Destroy();
}
else
{
BlowUp(Location);
}
}
}
else if (Other != Instigator && Other.IsA('Pawn'))
BlowUp(Location);
}
}

state OnGround
{
simulated function BeginState()
{
PlayAnim('hit');
SetTimer(RestTime, false);
}

simulated function Timer()
{
if (bDrip)
{
bDrip = false;
SetCollisionSize(default.CollisionHeight, default.CollisionRadius);
Velocity = PhysicsVolume.Gravity * 0.2;
SetPhysics(PHYS_Falling);
bCollideWorld = true;
bCheckedsurface = false;
bProjTarget = false;
LoopAnim('flying', 1.0);
GotoState('Flying');
}
else
{
BlowUp(Location);
}
}

simulated function ProcessTouch(Actor Other, Vector HitLocation)
{
if (Other.IsA('Pawn'))
{
bDrip = false;
SetTimer(TouchDetonationDelay, false);
}
}

function TakeDamage( int Damage, Pawn InstigatedBy, Vector HitLocation, Vector Momentum, class<DamageType> DamageType )
{
if (DamageType.default.bDetonatesGoop)
{
bDrip = false;
SetTimer(0.1, false);
}
}

simulated function AnimEnd(int Channel)
{
local float DotProduct;

if (!bCheckedSurface)
{
DotProduct = SurfaceNormal dot Vect(0,0,-1);
if (DotProduct > 0.7)
{
PlayAnim('Drip', 0.66);
bDrip = true;
SetTimer(DripTime, false);
if (bOnMover)
BlowUp(Location);
}
else if (DotProduct > -0.5)
{
PlayAnim('Slide', 1.0);
if (bOnMover)
BlowUp(Location);
}
bCheckedSurface = true;
}
}

simulated function MergeWithGlob(int AdditionalGoopLevel)
{
local int NewGoopLevel, ExtraSplash;
NewGoopLevel = AdditionalGoopLevel + GoopLevel;
if (NewGoopLevel > MaxGoopLevel)
{
Rand3 = (Rand3 + 1) % 3;
ExtraSplash = Rand3;
if (Role == ROLE_Authority)
SplashGlobs(NewGoopLevel - MaxGoopLevel + ExtraSplash);
NewGoopLevel = MaxGoopLevel - ExtraSplash;
}
SetGoopLevel(NewGoopLevel);
SetCollisionSize(GoopVolume*10.0, GoopVolume*10.0);
PlaySound(ImpactSound, SLOT_Misc);
PlayAnim('hit');
bCheckedSurface = false;
SetTimer(RestTime, false);
}

}

function BlowUp(Vector HitLocation)
{
if (Role == ROLE_Authority)
{
Damage = BaseDamage + Damage * GoopLevel;
DamageRadius = DamageRadius * GoopVolume;
MomentumTransfer = MomentumTransfer * GoopVolume;
if (Physics == PHYS_Flying) MomentumTransfer *= 0.5;
DelayedHurtRadius(Damage, DamageRadius, MyDamageType, MomentumTransfer, HitLocation);
}

PlaySound(ExplodeSound, SLOT_Misc);

Destroy();
//GotoState('shriveling');
}

function SplashGlobs(int NumGloblings)
{
local int g;
local BioGlob NewGlob;
local Vector VNorm;

for (g=0; g<NumGloblings; g++)
{
NewGlob = Spawn(Class, self,, Location+GoopVolume*(CollisionHeight+4.0)*SurfaceNormal);
if (NewGlob != None)
{
NewGlob.Velocity = (GloblingSpeed + FRand()*150.0) * (SurfaceNormal + VRand()*0.8);
if (Physics == PHYS_Falling)
{
VNorm = (Velocity dot SurfaceNormal) * SurfaceNormal;
NewGlob.Velocity += (-VNorm + (Velocity - VNorm)) * 0.1;
}
}
//else log("unable to spawn globling");
}
}

state Shriveling
{
simulated function BeginState()
{
bProjTarget = false;
PlayAnim('shrivel', 1.0);
}

simulated function AnimEnd(int Channel)
{
Destroy();
}

simulated function ProcessTouch(Actor Other, Vector HitLocation)
{
}
}

simulated function SetGoopLevel( int NewGoopLevel )
{
GoopLevel = NewGoopLevel;
GoopVolume = sqrt(float(GoopLevel));
SetDrawScale(GoopVolume*default.DrawScale);
LightBrightness = Min(100 + 15*GoopLevel, 255);
LightRadius = 1.7 + 0.2*GoopLevel;
}

defaultproperties
{
GoopLevel=1
GoopVolume=1.0
MaxGoopLevel=5
Speed=2000.0
TossZ=0.0
GloblingSpeed=200.0
BaseDamage=20.0
Damage=23.0 // full load = 135 damage
DamageRadius=120.0
MomentumTransfer=40000
bMergeGlobs=true
RestTime=2.25
DripTime=1.8
TouchDetonationDelay=0.15
MyDamageType=class'DamTypeBioGlob'
Physics=PHYS_Falling
Mesh=Mesh'XWeapons_rc.GoopMesh'
Skins(0)=FinalBlend'GoopFB'
DrawScale=1.2
AmbientGlow=80
bProjTarget=false
CollisionRadius=2
CollisionHeight=2
SoundRadius=100
SoundVolume=255
LifeSpan=20.0
bUnlit=true
RemoteRole=ROLE_SimulatedProxy
bNetTemporary=false
ExplodeSound=Sound'WeaponSounds.BioRifle.BioRifleGoo1'
ImpactSound=Sound'WeaponSounds.BioRifle.BioRifleGoo2'
bDynamicLight=true
LightType=LT_Steady
LightEffect=LE_QuadraticNonIncidence
LightBrightness=190
LightHue=82
LightSaturation=10
LightRadius=0.6
bSwitchToZeroCollision=true
bOnlyDirtyReplication=true
}


Ok, here is the LavaFire (the one that relates to this package)

class LavaFire extends ProjectileFire;

function DrawMuzzleFlash(Canvas Canvas)
{
if (FlashEmitter != None)
FlashEmitter.SetRotation(Weapon.Rotation);
Super.DrawMuzzleFlash(Canvas);
}

function float MaxRange()
{
return 1500;
}

defaultproperties
{
AmmoClass=class'LavaAmmo'
AmmoPerFire=2

FireAnim=Fire
FireEndAnim=None

ProjectileClass=class'LavaGlob'
FireRate=0.33

ProjSpawnOffset=(X=20,Y=9,Z=-6)
FlashEmitterClass=class'XEffects.BioMuzFlash1st'
FireSound=Sound'WeaponSounds.BioRifle.BioRifleFire'

FireForce="BioRifleFire" // jdf

bSplashDamage=true
bRecommendSplashDamage=true
BotRefireRate=0.8
bTossed=true

ShakeOffsetMag=(X=0.0,Y=0.0,Z=-2.0)
ShakeOffsetRate=(X=0.0,Y=0.0,Z=1000.0)
ShakeOffsetTime=1.8
ShakeRotMag=(X=70.0,Y=0.0,Z=0.0)
ShakeRotRate=(X=1000.0,Y=0.0,Z=0.0)
ShakeRotTime=1.8
}


And here is the Error: Error, Type mismatch in '='. Compile aborted due to errors. 1 error(s), 0 warning(s).

Error found!
NewGlob = Spawn(Class, self,, Location+GoopVolume*(CollisionHeight+4.0)*SurfaceNormal);
EvilDrWong is helping me fix it

ROFL 451
14th Mar 2004, 04:57 PM
WeaponClass=class'LavaCaster'

bSkeletize=True

bDetonatesGoop=true
bDelayedDamage=true


Can I put the skeletize part there?

ROFL 451
14th Mar 2004, 05:37 PM
Where do I enter the texture for a charged Bio Glob? because I was able to enter a texture for LavaGlob (BioGlob) but LavaChargedFire (BioChargedFire) shoots a bigger projectile, and I don't know where I can specify the skin.

Also, how do I get to the little splotch left over after a bio glob explodes, because it doesn't help to have a lava glob explode in a little green cloud. I need to change the little green cloud, and the green splat. If anyone can tell me where I can get those, it would be greatly appreciated!

Donator
15th Mar 2004, 02:12 AM
BioFire and BioChargedFire spawn the same class of projectile ("BioGlob"). BioChargedFire changes a few variables of the glob after spawning (to make it bigger and badder) through the SetGoopLevel function.

what you seek is in class BioGlob
A) to change the little green "Poof!" when the globs explode, just spawn different FX classes

simulated function Destroyed()
{
if ( !bNoFX && EffectIsRelevant(Location,false) )
{
Spawn(class'xEffects.GoopSmoke');
Spawn(class'xEffects.GoopSparks');
}
if ( Fear != None )
Fear.Destroy();
if (Trail != None)
Trail.Destroy();
Super.Destroyed();
}


and
B) change this line in BioGlob, it's about the 20th in "auto state flying", for a different decal texture

...
spawn(class'BioDecal',,,, rotator(-HitNormal));
...

ROFL 451
15th Mar 2004, 09:26 AM
BioFire and BioChargedFire spawn the same class of projectile ("BioGlob"). BioChargedFire changes a few variables of the glob after spawning (to make it bigger and badder) through the SetGoopLevel function.

what you seek is in class BioGlob
A) to change the little green "Poof!" when the globs explode, just spawn different FX classes

simulated function Destroyed()
{
if ( !bNoFX && EffectIsRelevant(Location,false) )
{
Spawn(class'xEffects.GoopSmoke');
Spawn(class'xEffects.GoopSparks');
}
if ( Fear != None )
Fear.Destroy();
if (Trail != None)
Trail.Destroy();
Super.Destroyed();
}


and
B) change this line in BioGlob, it's about the 20th in "auto state flying", for a different decal texture

...
spawn(class'BioDecal',,,, rotator(-HitNormal));
...


About the texturing LavaChargedFire, I found my error. It gave the correct deathstring when I killed with small globs (secondary) but killing with primary (big glob) gave me Bio Glob texture, and bio rifle deathstring. I found out, after going into LavaChargedFire that it said:
MyDamageType:DamTypeBioGlob = changed to DamTypeLavaGlob. And all was well.

Also, do you think it would be possible to simply retexture the poof! and the splat to lava texture/red?

Postal
15th Mar 2004, 10:44 AM
Yes, make a new effect, and give it red skin, perhaps something from firefx