UPawn - Remaking Pawn in UnrealScript
Posted: Mon Feb 27, 2017 7:30 pm
Do you know the Pawn class? Chances are you do. You know, that ugly, native, unflexible, boring class which is hard to extend and harsh to subclass.
Well, not for long!
Presenting, UPawn. Well, it's not done yet, but this pre-alpha code compiles. Whenever it does something I'll test it.
In fact, this is a remade version of Pawn, which uses the projectile physics to be able to walk on surfaces in a flexible way, but that's not it! It also supports Fun, and in the future, it'll have many more features!
I know this project is going to be VERY hard to code. That's why I'm a programmer!
Well, not for long!
Presenting, UPawn. Well, it's not done yet, but this pre-alpha code compiles. Whenever it does something I'll test it.
In fact, this is a remade version of Pawn, which uses the projectile physics to be able to walk on surfaces in a flexible way, but that's not it! It also supports Fun, and in the future, it'll have many more features!
Code: Select all
//=============================================================================
// UPawn.
//=============================================================================
class UPawn expands Actor;
enum PawnType
{
PT_None,
PT_Native,
PT_New,
PT_Both
};
enum PawnPhysics
{
PP_Walking,
PP_Falling,
PP_Swimming,
PP_Flying
};
enum NavigationClass
{
NC_Breadcrumb,
Nc_Native
};
struct WeaponUse
{
var() float MinRange, MaxRange;
var() float AverageDmg;
var() float SplashRange;
var() float ProjSpeed;
var() float ShootRate;
};
struct AnyPawn
{
var() PawnType ThisType;
var() Pawn Native;
var() UPawn New;
};
// UPhysics.
var(UPhysics) float MaxFloorPitch;
var(UPhysics) Vector MovementBob;
var(UPhysics) float JumpSpeed;
var(UPhysics) float WalkSpeed;
var(UPhysics) AnyPawn Mount;
// Artificial Intelligence of UPawn.
var(AI) float EyeHeight;
var(AI) float Cowardness;
var(AI) float Smartness;
var(AI) float Boredness;
var(AI) float Eagerness; // how fast the fun of playing only a single Toy is lost
var(AI) class<Weapon> FavoriteGun;
var(AI) WeaponUse GunStats;
var(AI) Pawn Enemies[32];
var(AI) Pawn PriorityEnemy;
var(AI) NavigationClass NavType;
var Actor Toy;
var float ToyStrenght;
var int PlayTimes;
// Inventory stuff.
var(PawnInv) Inventory StartingInv[64];
var(PawnInv) Weapon CurrentWeapon;
var(Anim) float IdleSpeed;
var(Anim) float BoredModifier; // multiplies idle anim speed when bored
var Rotator FloorNormal;
var Vector WalkOffset;
var Vector OldVel;
var Actor NvCurrent;
var Actor NvNext;
var int PathSize;
var Inventory Inv;
var float CurrentSpeed;
var name InterruptingWalk;
var name OldState;
var bool bMoving;
simulated function PreBeginPlay()
{
local Vector v, n;
v = Location;
v.Z -= 16384;
Trace(v, n, v);
FloorNormal = Rotator(n);
}
simulated function bool ActorCloser(Actor Other, Actor aFrom)
{
return aFrom == None || VSize(Other.Location - Location) < VSize(aFrom.Location - Location);
}
simulated function WalkToward(Actor Target, float Speed, bool bStrafe)
{
WalkNormal(Rotator(Target.Location - Location).Yaw, VSize(Location - Target.Location), Speed, bStrafe);
}
simulated function WalkTo(Vector Target, float Speed, bool bStrafe)
{
WalkNormal(Rotator(Target - Location).Yaw, VSize(Location - Target), Speed, bStrafe);
}
simulated function WalkNormal(float Angle, float Distance, float Speed, bool bStrafe)
{
local Rotator Dir;
Dir = FloorNormal;
Dir.Yaw = Angle;
if ( !bStrafe )
SetRotation(Dir);
WalkOffset += Vector(Dir) * Distance;
CurrentSpeed = WalkSpeed * Speed;
OldState = GetStateName();
GoToState('Walking');
}
simulated function Actor NextTo(Actor Target)
{
local Breadcrumb Closest, B;
local NavigationHelper H;
if ( Breadcrumb(NvCurrent) != None )
{
foreach AllActors(class'Breadcrumb', B)
if ( ActorCloser(B, Closest) )
Closest = B;
NvNext = Breadcrumb(NvCurrent).FindPathToBreadcrumb(Closest).Next;
}
else if ( NavigationPoint(NvCurrent) != None )
{
H = Spawn(class'NavigationHelper', self);
H.LoadPathToward(Target);
NvNext = H.Helped(true);
}
return NvNext;
}
simulated function bool Walkable(vector Normal)
{
return Rotator(Normal).Pitch / 65535 < MaxFloorPitch;
}
simulated function StopWalking(name NewState)
{
if ( IsInState('Walking') )
InterruptingWalk = NewState;
}
simulated function Tick(float TimeDelta)
{
if ( bMoving )
{
Velocity = OldVel;
bMoving = false;
}
}
simulated function GotFun(Actor Source, float Strenght)
{
Boredness -= Strenght;
if ( Source == Toy )
{
ToyStrenght -= PlayTimes * Eagerness - Strenght;
PlayTimes++;
return;
}
if ( Strenght > ToyStrenght )
{
Toy = Source;
ToyStrenght = Strenght;
PlayTimes = 0;
}
}
simulated function TickMove(Vector NewLocation)
{
Velocity = NewLocation - Location;
OldVel = Velocity;
bMoving = true;
}
simulated function HitWall(vector HitNormal, Actor Wall)
{
Landed(HitNormal);
}
simulated function Landed(vector Normal)
{
if ( !Walkable(Normal) )
return;
FloorNormal = Rotator(Normal);
}
auto state Idle
{
function Timer()
{
Boredness += 1;
}
Begin:
SetTimer(0.5, true);
if ( Boredness > 16 )
GoToState('Bored');
LoopAnim('Idle', IdleSpeed);
}
function Roam()
{
local Vector v, Norm, f;
v = Location + VRand() * 60;
while ( !FastTrace(v) )
v = Location + VRand() * 60;
f = v;
f.Z -= CollisionHeight * 1.6;
Trace(v, Norm, f, v);
WalkTo(v, 0.9, false);
}
state Bored
{
function Timer()
{
Boredness += 1;
if ( FRand() < Eagerness )
Roam();
}
Begin:
LoopAnim('Idle', IdleSpeed + BoredModifier);
if ( Boredness > 36 )
Roam();
}
state Walking
{
function EndWalk()
{
GoToState(OldState);
}
function Tick(float TimeDelta)
{
while ( VSize(WalkOffset) > (CurrentSpeed * 2.0) )
{
if ( InterruptingWalk != 'None' )
{
EndWalk();
GoToState(InterruptingWalk);
}
else
{
TickMove(Location + Normal(WalkOffset) * CurrentSpeed);
WalkOffset -= Normal(WalkOffset);
}
}
EndWalk();
}
}