forked from Mirrors/openclonk
Crosshair: Use analog stick input properly
- Crosshair doesn't work with a dpad anymore. Supporting dpads adds unnecessary complexity, as a gamepad user with dpad will never be competitive with mouse users. - Crosshair isn't bound to item usage anymore, but will always show when the analog stick is outside of a deadzone. Future planned feature: Also use the actual strength to allow distance input in addition to direction. This is used heavily by Knüppeln.c4s.qteditor^2
parent
93dcb1d729
commit
b8c8bf825c
|
@ -5,61 +5,69 @@
|
||||||
Virtual cursor for gamepad controls
|
Virtual cursor for gamepad controls
|
||||||
*/
|
*/
|
||||||
|
|
||||||
local crew, angle, dirx, diry, xpos,ypos, analogaim, aiming, menu;
|
local crew, angle, xpos, ypos, aiming, menu;
|
||||||
|
|
||||||
static const CURSOR_Radius = 100;
|
static const CURSOR_Radius = 100;
|
||||||
|
// This is supposed to be a constant, but C4Script doesn't allow constant expressions there.
|
||||||
|
private func CURSOR_Deadzone() { return PLRCON_MaxStrength / 5; }
|
||||||
|
|
||||||
protected func Initialize()
|
protected func Initialize()
|
||||||
{
|
{
|
||||||
this["Visibility"] = VIS_None;
|
SetVisibility(false);
|
||||||
dirx = diry = xpos = ypos = 0;
|
xpos = ypos = 0;
|
||||||
aiming = false;
|
aiming = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func FxMoveTimer()
|
public func FxMoveTimer()
|
||||||
{
|
{
|
||||||
var speed = 0;
|
|
||||||
var dpad_rotatespeed = 35;
|
|
||||||
|
|
||||||
// dpad mode
|
|
||||||
if(diry)
|
|
||||||
{
|
|
||||||
if (diry < 0) speed = -Sin(angle,100,10);
|
|
||||||
else if (diry > 0) speed = +Sin(angle,100,10);
|
|
||||||
angle += dpad_rotatespeed*speed/100;
|
|
||||||
UpdateAnalogpadPos();
|
|
||||||
}
|
|
||||||
if(dirx)
|
|
||||||
{
|
|
||||||
if (dirx < 0) speed = -Cos(angle,100,10);
|
|
||||||
else if (dirx > 0) speed = +Cos(angle,100,10);
|
|
||||||
angle += dpad_rotatespeed*speed/100;
|
|
||||||
UpdateAnalogpadPos();
|
|
||||||
}
|
|
||||||
// analog pad mode
|
|
||||||
if(!dirx && !diry)
|
|
||||||
{
|
|
||||||
var target_angle = Angle(0,0,xpos,ypos)*10;
|
var target_angle = Angle(0,0,xpos,ypos)*10;
|
||||||
var analog_strength = BoundBy(Sqrt(xpos*xpos+ypos*ypos),0,100);
|
|
||||||
|
|
||||||
|
if (!Visible() && !InDeadzone())
|
||||||
|
{
|
||||||
|
// The player moved the aiming stick while the crosshair wasn't visible: Use angle directly.
|
||||||
|
angle = target_angle;
|
||||||
|
SetVisibility(true);
|
||||||
|
}
|
||||||
|
else if (!InDeadzone())
|
||||||
|
{
|
||||||
|
// Smooth small movements of the stick while the crosshair is visible.
|
||||||
var angle_diff = Normalize(target_angle - angle, -1800, 10);
|
var angle_diff = Normalize(target_angle - angle, -1800, 10);
|
||||||
if (angle_diff == 0) angle_diff = 1;
|
if (Abs(angle_diff) < 450)
|
||||||
|
angle = angle + angle_diff / 8;
|
||||||
angle = angle + angle_diff * analog_strength / 100 / 8;
|
else
|
||||||
|
angle = target_angle;
|
||||||
|
}
|
||||||
|
else if (!aiming)
|
||||||
|
{
|
||||||
|
// The player doesn't touch the stick and no item is using the crosshair right now.
|
||||||
|
SetVisibility(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdatePosition();
|
UpdatePosition();
|
||||||
if(aiming) crew->TriggerHoldingControl();
|
crew->TriggerHoldingControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
private func UpdateAnalogpadPos()
|
private func AnalogStrength() { return BoundBy(Sqrt(xpos*xpos+ypos*ypos), 0, PLRCON_MaxStrength); }
|
||||||
|
private func InDeadzone() { return AnalogStrength() < CURSOR_Deadzone(); }
|
||||||
|
private func Visible() { return this.Visibility != VIS_None; }
|
||||||
|
|
||||||
|
// Updates the visibility, returing true if it was changed.
|
||||||
|
private func SetVisibility(bool visible)
|
||||||
{
|
{
|
||||||
xpos = Sin(angle/10,100);
|
var newvis, oldvis;
|
||||||
ypos = Cos(angle/10,-100);
|
if (visible)
|
||||||
|
newvis = VIS_Owner;
|
||||||
|
else
|
||||||
|
newvis = VIS_None;
|
||||||
|
oldvis = this.Visibility;
|
||||||
|
this.Visibility = newvis;
|
||||||
|
return newvis != oldvis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func StartAim(object clonk, bool stealth, object GUImenu)
|
public func StartAim(object clonk, bool stealth, object GUImenu)
|
||||||
{
|
{
|
||||||
|
aiming = true;
|
||||||
|
|
||||||
// only reinitialize angle if the crosshair hasn't been there before
|
// only reinitialize angle if the crosshair hasn't been there before
|
||||||
if(!GetEffect("Move",this))
|
if(!GetEffect("Move",this))
|
||||||
{
|
{
|
||||||
|
@ -80,21 +88,14 @@ public func StartAim(object clonk, bool stealth, object GUImenu)
|
||||||
menu = nil;
|
menu = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set starting position for analog pad
|
// Aim somewhere useful if the crosshair wasn't visible before.
|
||||||
UpdateAnalogpadPos();
|
if (SetVisibility(true))
|
||||||
|
angle = 800*(clonk->GetDir()*2-1);
|
||||||
|
|
||||||
crew = clonk;
|
crew = clonk;
|
||||||
UpdatePosition();
|
UpdatePosition();
|
||||||
RemoveEffect("Move",this);
|
RemoveEffect("Move",this);
|
||||||
AddEffect("Move",this,1,1,this);
|
AddEffect("Move",this,1,1,this);
|
||||||
|
|
||||||
if(!stealth)
|
|
||||||
{
|
|
||||||
this["Visibility"] = VIS_Owner;
|
|
||||||
crew->SetComDir(COMD_Stop);
|
|
||||||
aiming = true;
|
|
||||||
EnableKeyAimControls(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func UpdatePosition()
|
private func UpdatePosition()
|
||||||
|
@ -112,65 +113,34 @@ private func UpdatePosition()
|
||||||
|
|
||||||
private func MirrorCursor()
|
private func MirrorCursor()
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
angle = -Normalize(angle,-1800,10);
|
angle = -Normalize(angle,-1800,10);
|
||||||
UpdateAnalogpadPos();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func StopAim()
|
public func StopAim()
|
||||||
{
|
{
|
||||||
RemoveEffect("Move",this);
|
|
||||||
this["Visibility"] = VIS_None;
|
|
||||||
dirx = 0;
|
|
||||||
diry = 0;
|
|
||||||
EnableKeyAimControls(false);
|
|
||||||
analogaim = false;
|
|
||||||
aiming = false;
|
aiming = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private func EnableKeyAimControls(bool enable)
|
|
||||||
{
|
|
||||||
SetPlayerControlEnabled(GetOwner(), CON_AimUp, enable);
|
|
||||||
SetPlayerControlEnabled(GetOwner(), CON_AimDown, enable);
|
|
||||||
SetPlayerControlEnabled(GetOwner(), CON_AimLeft, enable);
|
|
||||||
SetPlayerControlEnabled(GetOwner(), CON_AimRight, enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public func IsAiming()
|
public func IsAiming()
|
||||||
{
|
{
|
||||||
return aiming;
|
return aiming;
|
||||||
}
|
}
|
||||||
|
|
||||||
public func Aim(int ctrl, object clonk, int strength, int repeat, int release)
|
public func Aim(int ctrl, object clonk, int strength, int repeat, int status)
|
||||||
{
|
{
|
||||||
// start (stealth) aiming
|
// start (stealth) aiming
|
||||||
if(!GetEffect("Move",this))
|
if(!GetEffect("Move",this))
|
||||||
StartAim(clonk,true);
|
StartAim(clonk,true);
|
||||||
|
|
||||||
// aiming with analog pad
|
// aiming with analog pad
|
||||||
if (ctrl == CON_AimAxisUp || ctrl == CON_AimAxisDown || ctrl == CON_AimAxisLeft || ctrl == CON_AimAxisRight)
|
if (status == CONS_Moved &&
|
||||||
|
(ctrl == CON_AimAxisUp || ctrl == CON_AimAxisDown || ctrl == CON_AimAxisLeft || ctrl == CON_AimAxisRight))
|
||||||
{
|
{
|
||||||
dirx = diry = 0;
|
|
||||||
|
|
||||||
if(ctrl == CON_AimAxisUp) ypos = -strength;
|
if(ctrl == CON_AimAxisUp) ypos = -strength;
|
||||||
if(ctrl == CON_AimAxisDown) ypos = strength;
|
if(ctrl == CON_AimAxisDown) ypos = strength;
|
||||||
if(ctrl == CON_AimAxisLeft) xpos = -strength;
|
if(ctrl == CON_AimAxisLeft) xpos = -strength;
|
||||||
if(ctrl == CON_AimAxisRight) xpos = strength;
|
if(ctrl == CON_AimAxisRight) xpos = strength;
|
||||||
analogaim = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// stop
|
|
||||||
else if (release && !analogaim)
|
|
||||||
{
|
|
||||||
if(ctrl == CON_AimUp || ctrl == CON_AimDown) diry = 0;
|
|
||||||
else if(ctrl == CON_AimLeft || ctrl == CON_AimRight) dirx = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if(!release /*&& !repeat */ && !analogaim)
|
|
||||||
{
|
|
||||||
if(ctrl == CON_AimUp) diry = -1;
|
|
||||||
else if(ctrl == CON_AimDown) diry = 1;
|
|
||||||
else if(ctrl == CON_AimLeft) dirx = -1;
|
|
||||||
else if(ctrl == CON_AimRight) dirx = 1;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -239,8 +239,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
|
||||||
CON_Left is still called afterwards. So if the clonk finally starts to
|
CON_Left is still called afterwards. So if the clonk finally starts to
|
||||||
aim, the virtual cursor already aims into the direction in which he ran
|
aim, the virtual cursor already aims into the direction in which he ran
|
||||||
*/
|
*/
|
||||||
if (ctrl == CON_AimAxisUp || ctrl == CON_AimAxisDown || ctrl == CON_AimAxisLeft || ctrl == CON_AimAxisRight
|
if (ctrl == CON_AimAxisUp || ctrl == CON_AimAxisDown || ctrl == CON_AimAxisLeft || ctrl == CON_AimAxisRight)
|
||||||
|| ctrl == CON_AimUp || ctrl == CON_AimDown || ctrl == CON_AimLeft || ctrl == CON_AimRight)
|
|
||||||
{
|
{
|
||||||
var success = VirtualCursor()->Aim(ctrl,this,strength,repeat,status);
|
var success = VirtualCursor()->Aim(ctrl,this,strength,repeat,status);
|
||||||
// in any case, CON_Aim* is called but it is only successful if the virtual cursor is aiming
|
// in any case, CON_Aim* is called but it is only successful if the virtual cursor is aiming
|
||||||
|
|
|
@ -59,26 +59,6 @@
|
||||||
DefaultDisabled=1
|
DefaultDisabled=1
|
||||||
CoordinateSpace=Viewport
|
CoordinateSpace=Viewport
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=AimUp
|
|
||||||
DefaultDisabled=1
|
|
||||||
Hold=1
|
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=AimDown
|
|
||||||
DefaultDisabled=1
|
|
||||||
Hold=1
|
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=AimLeft
|
|
||||||
DefaultDisabled=1
|
|
||||||
Hold=1
|
|
||||||
|
|
||||||
[ControlDef]
|
|
||||||
Identifier=AimRight
|
|
||||||
DefaultDisabled=1
|
|
||||||
Hold=1
|
|
||||||
|
|
||||||
[ControlDef]
|
[ControlDef]
|
||||||
Identifier=AimAxisUp
|
Identifier=AimAxisUp
|
||||||
GUIName=$CON_AimAxisUp$
|
GUIName=$CON_AimAxisUp$
|
||||||
|
|
Loading…
Reference in New Issue