My original mechanic was interacting magnets. However, this problem was solved easily enough by toggling the properties of a Radial Force Actor which is attached to a Kactor. So, I explored more options - I wanted an easier way to move the magnet (by now ball-shaped) around the map. I became determined to get some form of "point and click" mechanic working, where the ball would go wherever you shot. I am extremely happy with the result - it is 100% functional for flat surfaces, and inclines can be worked around without much hassle.
I will organize this documentation as a series of problems.
Problem #1: Getting A Radial Force Actor to Move to a Damaged Trigger's Location
The idea is essentially to be able to shoot a trigger, and have a radial force actor spawn at that trigger's location. This radial force actor will be what attracts the ball/object. The trigger is obviously giving the location of where your bullet hit.
First, we must create a Dynamic Trigger actor, which can be found near the bottom of the actor classes browser. Alternatively, you may simply copy/paste the following code directly into any of the level editing viewports:
Begin Map
Begin Level
Begin Actor Class=Trigger_Dynamic Name=Trigger_Dynamic_9 Archetype=Trigger_Dynamic'Engine.Default__Trigger_Dynamic'
Begin Object Class=CylinderComponent Name=CollisionCylinder ObjName=CylinderComponent_275 Archetype=CylinderComponent'Engine.Default__Trigger_Dynamic:CollisionCylinder'
ReplacementPrimitive=None
bAcceptsDynamicDecals=False
bAcceptsFoliage=False
BlockActors=True
BlockNonZeroExtent=False
LightingChannels=(bInitialized=True,Dynamic=True)
Name="CylinderComponent_275"
ObjectArchetype=CylinderComponent'Engine.Default__Trigger_Dynamic:CollisionCylinder'
End Object
Begin Object Class=SpriteComponent Name=Sprite ObjName=SpriteComponent_38 Archetype=SpriteComponent'Engine.Default__Trigger_Dynamic:Sprite'
ReplacementPrimitive=None
LightingChannels=(bInitialized=True,Dynamic=True)
Name="SpriteComponent_38"
ObjectArchetype=SpriteComponent'Engine.Default__Trigger_Dynamic:Sprite'
End Object
CylinderComponent=CylinderComponent'CylinderComponent_275'
Components(0)=SpriteComponent'SpriteComponent_38'
Components(1)=CylinderComponent'CylinderComponent_275'
Location=(X=0,Y=0,Z=2.000000)
CollisionType=COLLIDE_BlockWeapons
bBlockActors=True
Tag="Trigger_Dynamic"
CollisionComponent=CylinderComponent'CylinderComponent_275'
Name="Trigger_Dynamic_9"
ObjectArchetype=Trigger_Dynamic'Engine.Default__Trigger_Dynamic'
End Actor
End Level
Begin Surface
End Surface
End Map
If you added a fresh dynamic trigger instead of copying my code, you must set "Collision Type" to "COLLIDE_BlockWeapons" under the Collision expansion box in order for it to actually detect damage.
Next, we need a Radial Force Actor. Again, you can either grab one from the actor classes browser, or copy/paste the following code:
Begin Map
Begin Level
Begin Actor Class=RB_RadialForceActor Name=RB_RadialForceActor_2 Archetype=RB_RadialForceActor'Engine.Default__RB_RadialForceActor'
Begin Object Class=DrawSphereComponent Name=DrawSphere0 ObjName=DrawSphereComponent_0 Archetype=DrawSphereComponent'Engine.Default__RB_RadialForceActor:DrawSphere0'
SphereRadius=10000.000000
ReplacementPrimitive=None
LightingChannels=(bInitialized=True,Dynamic=True)
Name="DrawSphereComponent_0"
ObjectArchetype=DrawSphereComponent'Engine.Default__RB_RadialForceActor:DrawSphere0'
End Object
Begin Object Class=SpriteComponent Name=Sprite ObjName=SpriteComponent_91 Archetype=SpriteComponent'Engine.Default__RB_RadialForceActor:Sprite'
ReplacementPrimitive=None
LightingChannels=(bInitialized=True,Dynamic=True)
Name="SpriteComponent_91"
ObjectArchetype=SpriteComponent'Engine.Default__RB_RadialForceActor:Sprite'
End Object
RenderComponent=DrawSphereComponent'DrawSphereComponent_0'
ForceStrength=-25.000000
ForceRadius=10000.000000
CollideWithChannels=(Default=False,Pawn=False,Vehicle=False,Water=False,GameplayPhysics=False,EffectPhysics=False,Untitled2=False,Untitled3=False,Untitled4=False,Cloth=False,FluidDrain=False)
Components(0)=DrawSphereComponent'DrawSphereComponent_0'
Components(1)=SpriteComponent'SpriteComponent_91'
Location=(X=0,Y=0,Z=85.999992)
Tag="RB_RadialForceActor"
Name="RB_RadialForceActor_2"
ObjectArchetype=RB_RadialForceActor'Engine.Default__RB_RadialForceActor'
End Actor
End Level
Begin Surface
End Surface
End Map
If you chose to make your own, expand the "RB_RadialForceActor" drop down box, then expand "collide with channels" and uncheck every channel except for "Untitled 1". (Later we will put the ball/object on the same channel so that we make sure we are only attracting the objects we want to.) Finally, give the force a large radius (at least twice the size of your playable space) and a negative strength value; I chose -25, but you will want to play with that number depending on how "persuasive" you want your guidance system to be on your object of choice.
Now, we're ready to open Kismet. Create a new sequence called "Damage_Sets_Force_Location". (I like to keep things extremely organized)
Make sure you have the trigger selected in the viewport windows, then right-click in Kismet and create a "New Event Using Radial Force Actor" > "Take Damage".
Or, copy and paste the following code:
Begin Object Class=SeqEvent_TakeDamage Name=SeqEvent_TakeDamage_9
DamageThreshold=0.100000
DamageTypes(0)=Class'UTGame.UTDmgType_LinkBeam'
Originator=Trigger_Dynamic'Trigger_Dynamic_9'
MaxTriggerCount=0
bPlayerOnly=False
MaxWidth=229
OutputLinks(0)=(Links=((LinkedOp=SeqAct_GetLocationAndRotation'SeqAct_GetLocationAndRotation_4')),DrawY=794)
VariableLinks(0)=(DrawX=-640)
VariableLinks(1)=(DrawX=-566)
ObjInstanceVersion=3
ParentSequence=Sequence'Damage_Sets_Force_Location'
ObjPosX=-720
ObjPosY=728
ObjName="Trigger_Dynamic_9 Take Damage"
ObjComment="takingdamage"
DrawWidth=134
DrawHeight=121
Name="SeqEvent_TakeDamage_9"
ObjectArchetype=SeqEvent_TakeDamage'Engine.Default__SeqEvent_TakeDamage'
End Object
Again, there are several important options here that need to be changed if you did this yourself:
Damage Threshold should be turned down - I changed it to 0.100000
Damage Type needs to change to whatever weapon you want to use to guide the object.
Max Trigger Count must be set to 0.
Player Only needs to be unchecked.
Now, we need two new nodes - Get Location and Rotation and Set Actor Location. These can be left at default settings.
Connect the Take Damage trigger to the Get Location and Rotation node, then connect the Get Location and Rotation node to the Set Actor Location node.
Now we need 3 variables... create new Dynamic Trigger and Radial Force Actor object variables (by selecting the objects in the browser and then right-clicking in kismet...) and a new vector variable.
The entire setup should end up looking like this:
Problem #2: Getting the Trigger Setup to Work Wherever you Shoot
Theoretically, we could simply coat the entire floor of our level with these triggers, but this is extremely time consuming and unrealistic. There is, however, a simple solution using only a small amount of triggers.
For my setup, I duplicated the above trigger setup 7 times (so I ended up with 8 different triggers) and spaced them out on the floor in front of the player in a line, so that the collisions just barely overlapped. (You can view the collisions by hitting 'c') I then duplicated these 8 triggers together and moved them up in Z ONLY, and changed these new triggers back to No_Collision. These "extra" triggers will be important later.
My Rig:
(The idea behind this "line" of triggers is that, if we attach them to the player, they will always be right in the player's line of fire, and the individual triggers will determine how near/far a bullet hits. It may be advisable in your case to add more triggers to expand the distance the player can shoot in order to attract the object. For my purposes 8 worked just fine.)
Now, we must attach all 16 of these triggers to the player. This simply requires 16 Attach To Actor nodes in Kismet, so create a new sequence called "Attach Triggers to Actor" and create a new Attach To Actor node, a new All Players variable and 16 trigger variables based on your 16 triggers.
Under the Attach To Actor properties, uncheck "Hard Attach". Connect an "All Players" variable to the Target connector. At this point, Copy and Paste this setup until you have 16 of them. Then connect a different trigger variable to each of the Attachment connectors. Final setup should look like this...
repeated 15 more times. Connect them all. To finish, create a "Player Spawned" event and hook it up to the beginning.
*UNDER CONSTRUCTION*