Nick89/Fooling With TransSpider
Intro
Recently porkmanii released Beta 1.0 of his latest mutator attempt, the [TransSpider].
He gave it this description:
Ever wished your Translocator beacon could grow legs and walk around? Neither have I, but now it can!
Inspired by this little mod, I thought I would try to get into UnrealScript once again in order to fool around with this mod (add features etc).
Also revealing he would not have much time to work on it for a while, I thought I could attempt to flatten out some bugs and attempt some of the feature suggestions. (I still don't know how far I will be able to go with it).
This page is a Mini Journal of the things i attempt (in all my coding n00biness), the problems I encounter and the solutions I find. If i find no solutions at certain stages, I welcome people to help me! This is about me learning to UnrealScript more than anything.
Although I'm very much new to UnrealScript, i have lots of other coding experience under my belt, including plenty of OOP. I've had experience with:
- PHP
- C++
- Java (Only very little though)
- Visual Basic (VB6 and .NET)
- Quick Basic
- HTML, CSS (not that it counts )
Before we start
If you intend to read through this, I suggest you [familiarise yourself] with the features of the mutator by porkmanii.
I have made the original exported scripts available from my File Front account:
Still looking for my filefront password.
Feature Attempts/Bug Fixes
Slightly More Explosive (Unresolved)
The first feature I try and it all works well, all but one thing!
I decided for my first feature I would change the self-destruct explosion from a Grenade Explosion to a Leviathan Cannon Implosion.
I found the function, BlowUp, in the SpiderPawn code and some default properties which it utilised and created the following new function:
simulated function BlowUp(Vector HitLocation) { if (Role == ROLE_Authority) HurtRadius(Damage, DamageRadius, MyDamageType, MomentumTransfer, HitLocation); PlaySound(ExplodeSound, SLOT_Misc); if ( Role == ROLE_Authority && EffectIsRelevant(Location,false) ) Spawn(class'ONSMASCannonImplosionEffect'); // Previously ONSGrenadeExplosionEffect Destroy(); }
defaultproperties { Damage=6000.000000 //Previously 95 DamageRadius=2200.000000 // Previously 250 MomentumTransfer=50000.000000 MyDamageType=Class'OnslaughtFull.DamTypeMASCannon' //Previously Onslaught.DamTypeONSMine //ExplodeSound=SoundGroup'WeaponSounds.RocketLauncher.RocketLauncherFire' ExplodeSound=Sound'ONSVehicleSounds-S.MAS.MASBIGFire01' .... .... }
Most of which i was able to find from the Leviathan code itself. The damage and damage radius is actually somewhat interesting. The Leviathan explosion is actually 6 smaller explosions which happen consecutively, each explosion does 1000 damage and each consecutive explosion has a slightly bigger DamageRadius than the last (until the sixth which is 2200uu). Rather than repeating this effect, I just used the largest radius and the sum of all of the damage.
Now for the most part this worked fantastically, however a small bug from the original code became apparent once given a huge amount of Damage. The self destruct or death explosion would do no damage to PowerNodes and PowerCores if they were triggered whilst you were possessing the SpiderPawn.
Now looking at the class ONSPowerCore (Which is the base class for PowerCores and PowerNodes), the following snippet of code can be found in TakeDamage:
if (InstigatorController == None && damageType != None) return;
Which is saying that if the Pawn has no Controller, it won't take damage.
This suggests that we are Relinquishing the Controller before we cause the damage.
Unfortunately this is where i am lost. I can't find where this must be happening.
Here is where I am at with the code:
function Died(Controller Killer, class<DamageType> damageType, vector HitLocation) { if (bDeleteMe || Level.bLevelChange || Level.Game == None) return; // already destroyed, or level is being cleaned up Health = Min(0, Health); if (DrivenVehicle != None) DrivenVehicle.DriverDied(); Level.Game.NotifyKilled(Killer, Controller, self); // discard Inventory, but not the flag! PlayerReplicationInfo = none; Level.Game.DiscardInventory(self); DrivenVehicle = None; if (IsHumanControlled()) PlayerController(Controller).ForceDeathUpdate(); BlowUp(HitLocation); } simulated function BlowUp(Vector HitLocation) { if (Role == ROLE_Authority) HurtRadius(Damage, DamageRadius, MyDamageType, MomentumTransfer, HitLocation); PlaySound(ExplodeSound, SLOT_Misc); if ( Role == ROLE_Authority && EffectIsRelevant(Location,false) ) Spawn(class'ONSMASCannonImplosionEffect'); // Previously ONSGrenadeExplosionEffect Destroy(); }
Died is called when you use the self destruct, or if the Spider actually dies.
Destroy has not been Overridden from UnrealPawn.
Nick89: Any thoughts?
Spider No Jump! (Success)
The problem was that the spider couldn't use UTJumpPads.
So i dug up the code for the Jump Pad and found the following slice of code:
event Touch(Actor Other) { if ( (UnrealPawn(Other) == None) || (Other.Physics == PHYS_None) ) return; PendingTouch = Other.PendingTouch; Other.PendingTouch = self; }
Once i had found the code the limiting factor was fairly obvious.
- UnrealPawn(Other) == None
- Will test if the Actor which has touched the Jump Pad is a UnrealPawn or SubClass? thereof.
The spider is a Pawn, and the tree structure of this area looks as follows:
+- Actor +- Pawn +- UnrealPawn
Which meant that our TransSpider did not meet the condition set by the UTJumpPad for a successful jump.
This was fairly easily fixed, a quick change from Pawn to UnrealPawn.
class ts_SpiderPawn extends UnrealPawn;
Allowing the Spider to Pickup and Use inventory (Success)
This feature was just something I decided I would like to do, but would take out in the future.
This fix was relatively easy. After perusing some of the properties which the Spider would now inherit and some of the code I found the following things.
function GiveWeapon(string aClassName ) { // never give weapons to Spiders } function bool AddInventory( inventory NewItem ) { // never allow inventory return false; } simulated function bool IsPlayerPawn() { // don't allow Spider to trigger objectives (or movers) return false; }
And in the deafault properties of UnrealPawn:
bCanPickupInventory=False bAcceptAllInventory=False
Yet another easy fix. I added these two properties as True to the default properties of the TransSpider UnrealPawn and commented out the "Rejection Code", which I discovered was the source of the Lifts(Movers) not working.
One last quick change to the default properties of the TransSpider UnrealPawn and we got our crosshair back too:
bSpecialCrosshair=True //BECOMES bSpecialCrosshair=False
All worked out fine here, although there is a problem with the Spider not dropping the flag. (ie. you can capture again and again and again). I am aware of where this problem is, however as this feature will be later removed, i'm not too concerned.
Give master the pickups you find
Yet to begin.
Discussion
Nick89: Any thoughts? Any thoughts with my PowerNode Problem?