I've implemented the corrupt data segment basis (check Wiki Appendix for further details).
Features implemented:
- the volume: replace pawn inventory by the checktool, allow the player to scan or heal the corrupt data segment
- the corrupt data segment: scan and heal mechanism implemented, display current scan or heal amount and corruptdata tag name on screen as well.
- send localmessage at scan and heal end
- 2 Damage types: (primary and secondary) used by corrupt data segment class to know what FireMode the player is using.
Temporary Feature:
- CheckTool: a basic weapon has been created, it inherits from the Enforcer (could be replaced later depends of what should the CheckTool looks like)
CheckTool secondary fire sucks but as I said it's temporary
Here are some pictures in Game:
Phase Scanning


Phase Healing


Message End Phase


Source Code
Corrupt Data Segment
class DataRun_CorruptDataSegment extends Actor
placeable;
var() string corruptDataTagName;
var() int scanDuration;
var() int healDuration;
var() string scanEndMessage;
var() string healEndMessage;
//this boolean is updated according to pawn location. true when pawn entering the
//volume and false when leaving. This is used to prevent scan or heal outside
//the volume
var bool segmentCanBeHit;
var float currentScanAmount;
var float currentHealAmount;
var float scanIncrement;
var float healIncrement;
event TakeDamage(int DamageAmount, Controller EventInstigator, vector HitLocation, vector Momentum, class<DamageType> DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser)
{
if(!segmentCanBeHit || self.IsInState('healed'))
return;
if(DataRun_CheckTool(DamageCauser) == None)
return;
//compute scan and heal increment
if(scanIncrement == -1 || healIncrement == -1)
{
scanIncrement = DataRun_CheckTool(DamageCauser).fireInterval[0] * 100 / scanDuration;
healIncrement = DataRun_CheckTool(DamageCauser).fireInterval[1] * 100 / healDuration;
}
if(DamageType == class'DataRun_CheckTool_DmgType_PrimaryFire' && currentScanAmount < 100)
{
GotoState('scanning');
}
if(DamageType == class'DataRun_CheckTool_DmgType_SecondaryFire' && currentScanAmount >= 100 && currentHealAmount < 100)
{
GotoState('healing');
}
}
state scanning
{
event TakeDamage(int DamageAmount, Controller EventInstigator, vector HitLocation, vector Momentum, class<DamageType> DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser)
{
if(!segmentCanBeHit || self.IsInState('healed') || DamageType != class'DataRun_CheckTool_DmgType_PrimaryFire')
return;
currentScanAmount += scanIncrement;
if(currentScanAmount >= 100)
{
PlayerController(EventInstigator).ReceiveLocalizedMessage(MessageClass,0,,,self);
GotoState('healing');
}
}
function BeginState(Name PreviousStateName)
{
//First we enter state increase scan amount
currentScanAmount += scanIncrement;
}
}
state healing
{
event TakeDamage(int DamageAmount, Controller EventInstigator, vector HitLocation, vector Momentum, class<DamageType> DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser)
{
if(!segmentCanBeHit || self.IsInState('healed') || DamageType != class'DataRun_CheckTool_DmgType_SecondaryFire')
return;
currentHealAmount += HealIncrement;
if(currentHealAmount >= 100)
{
PlayerController(EventInstigator).ReceiveLocalizedMessage(MessageClass,1,,,self);
GotoState('healed');
}
}
function BeginState(Name PreviousStateName)
{
//First we enter state increase heal amount
currentHealAmount += healIncrement;
}
}
//final state for corrup data segment
state healed
{
function BeginState(Name PreviousStateName)
{
}
}
simulated event PostRenderFor(PlayerController PC, Canvas Canvas, vector CameraPosition, vector CameraDir)
{
local float XL, YL, HealthX, TextXL;
local vector ScreenLoc;
local string ScreenName;
ScreenLoc = Canvas.Project(Location);
// make sure not clipped out
if (screenLoc.X < 0 ||
screenLoc.X >= Canvas.ClipX ||
screenLoc.Y < 0 ||
screenLoc.Y >= Canvas.ClipY)
{
return;
}
if(currentScanAmount > 0 && currentScanAmount < 100)
{
ScreenName = corruptDataTagName@"Scan Phase in Progress ...";
}
else if(currentHealAmount > 0 && currentHealAmount < 100)
{
ScreenName = corruptDataTagName@"Heal Phase in Progress ...";
}
else
{
ScreenName = "";
}
if(ScreenName != "")
{
Canvas.StrLen(ScreenName, TextXL, YL);
Canvas.DrawColor = class'UTHUD'.default.LightGreenColor;
Canvas.SetPos(ScreenLoc.X-0.5*TextXL,ScreenLoc.Y-60);
Canvas.DrawTextClipped(ScreenName, true);
}
if(currentScanAmount < 100)
{
HealthX = currentScanAmount;
}
else
{
HealthX = currentHealAmount;
}
XL = 100;
class'UTHUD'.static.DrawHealth(ScreenLoc.X-0.5*XL, ScreenLoc.Y - 50, HealthX, XL, 20, Canvas);
}
defaultproperties
{
scanDuration = 2
healDuration = 5
scanEndMessage = "scanning complete"
healEndMessage = "healing complete"
scanIncrement = -1
healIncrement = -1
currentScanAmount = -1
currentHealAmount = -1
MessageClass = class'DataRun_CorruptDataSegmentMessage';
Begin Object class=DynamicLightEnvironmentComponent Name=OnslaughtFlagLightEnvironment
bDynamic=FALSE
bCastShadows=FALSE
End Object
Components.Add(OnslaughtFlagLightEnvironment)
Begin Object class=CylinderComponent Name=CollisionCylinder ObjName=CollisionCylinder Archetype=CylinderComponent'Engine.Default__CylinderComponent'
CollisionHeight=25.000000
CollisionRadius=25.000000
CollideActors=True
BlockActors=true
BlockZeroExtent=true
BlockNonZeroExtent=true
HiddenGame=false
Name="CollisionCylinder"
ObjectArchetype=CylinderComponent'Engine.Default__CylinderComponent'
End Object
Components.Add(CollisionCylinder)
Begin Object class=StaticMeshComponent Name=StaticMeshComponent0
StaticMesh=StaticMesh'Pickups.PowerCell.Mesh.S_Pickups_PowerCell_Cell01'
LightEnvironment=OnslaughtFlagLightEnvironment
scale=2
End Object
Components.Add(StaticMeshComponent0)
bCanBeDamaged = true
bCollideActors = true
bBlockActors = true
CollisionComponent=CollisionCylinder
CollisionType=COLLIDE_CustomDefault
name="Default__DataRun_CorruptDataSegment"
ObjectArchetype=Actor'Engine.Default__Actor'
}Corrupt Data Volume
class DataRun_CorruptDataVolume extends PhysicsVolume
placeable;
var DataRun_CorruptDataSegment segmentActor;
var(ExistingSegment) string segmentTag;
var class<Weapon> checkToolClass;
var InventoryManager PawnBackupInvManager;
var Weapon PawnBackupWeapon;
simulated function PostBeginPlay()
{
local DataRun_CorruptDataSegment a;
foreach WorldInfo.AllActors(class'DataRun_CorruptDataSegment', a)
{
if(a.corruptDataTagName == segmentTag)
{
segmentActor = a;
break;
}
}
}
event PawnEnteredVolume(Pawn Other)
{
local PlayerController PC;
PC = PlayerController(Other.Controller);
if(PC != None)
{
//enable segment
segmentActor.segmentCanBeHit = true;
//enable postRender
UTHUD(PC.myHUD).AddPostRenderedActor(segmentActor);
giveCheckTool(Other);
}
}
event PawnLeavingVolume(Pawn Other)
{
local PlayerController PC;
PC = PlayerController(Other.Controller);
if(PC != None)
{
//disable segment
segmentActor.segmentCanBeHit = false;
//disable postRender
UTHUD(PC.myHUD).RemovePostRenderedActor(segmentActor);
restituteInventory(Other);
}
}
function giveCheckTool(Pawn P)
{
local Inventory inv;
local InventoryManager checkToolInvManager;
//backup inventoryManager and weapon
PawnBackupInvManager = P.InvManager;
PawnBackupWeapon = P.Weapon;
//set new inventory and select CheckTool Weapon
checkToolInvManager = spawn(class'UTInventoryManager');
UTInventoryManager(checkToolInvManager).bInfiniteAmmo = true;
checkToolInvManager.SetupFor(P);
P.InvManager = checkToolInvManager;
P.InvManager.CreateInventory(checkToolClass, true);
//we have to force CheckTool selection
Inv = P.FindInventoryType(checkToolClass);
P.InvManager.SetPendingWeapon(Weapon(Inv));
P.InvManager.ChangedWeapon();
}
function restituteInventory(Pawn P)
{
//restitute previous inventory
P.InvManager = PawnBackupInvManager;
if(PawnBackupWeapon != None)
{
P.InvManager.SetPendingWeapon(PawnBackupWeapon);
P.InvManager.ChangedWeapon();
}
}
defaultproperties
{
checkToolClass = class'DataRun_CheckTool'
}Corrupt Data Message
class DataRun_CorruptDataSegmentMessage extends UTLocalMessage;
static function string GetString(
optional int Switch,
optional bool bPRI1HUD,
optional PlayerReplicationInfo RelatedPRI_1,
optional PlayerReplicationInfo RelatedPRI_2,
optional Object OptionalObject
)
{
local DataRun_CorruptDataSegment CR;
CR = DataRun_CorruptDataSegment(OptionalObject);
if( CR != None)
{
switch(Switch)
{
case 0:
return CR.scanEndMessage;
case 1:
return CR.healEndMessage;
}
}
return "";
}
defaultproperties
{
bIsUnique=true
bCountInstances=true
DrawColor=(R=255,G=255,B=128,A=255)
FontSize=2
bIsConsoleMessage=false
MessageArea=5
}Temporary CheckTool
class DataRun_CheckTool extends UTWeap_Enforcer;
defaultproperties
{
WeaponFireTypes[0]=EWFT_InstantHit
WeaponFireTypes[1]=EWFT_InstantHit
InstantHitDamageTypes(0)=class'DataRun_CheckTool_DmgType_PrimaryFire'
InstantHitDamageTypes(1)=class'DataRun_CheckTool_DmgType_SecondaryFire'
FireInterval(0)=+0.25
FireInterval(1)=+0.25
InstantHitDamage(0)=0
InstantHitDamage(1)=0
FiringStatesArray(0)=WeaponFiring
FiringStatesArray(1)=WeaponFiring
}PrimaryFireDamageType
class DataRun_CheckTool_DmgType_PrimaryFire extends UTDamageType;
static function DoCustomDamageEffects(UTPawn ThePawn, class<UTDamageType> TheDamageType, const out TraceHitInfo HitInfo, vector HitLocation)
{
//Ze goggles! Zey do nuthing!!
}
defaultproperties
{
bUseTearOffMomentum=false
bCausedByWorld=false
bOverrideHitEffectColor=true
HitEffectColor=(R=0,G=0,B=0)
}SecondaryFireDamageType
class DataRun_CheckTool_DmgType_SecondaryFire extends UTDamageType;
static function DoCustomDamageEffects(UTPawn ThePawn, class<UTDamageType> TheDamageType, const out TraceHitInfo HitInfo, vector HitLocation)
{
//Ze goggles! Zey do nuthing!!
}
defaultproperties
{
bUseTearOffMomentum=false
bCausedByWorld=false
bOverrideHitEffectColor=true
HitEffectColor=(R=0,G=0,B=0)
}Questions? Comments?








