forked from Mirrors/openclonk
178 lines
3.8 KiB
C
178 lines
3.8 KiB
C
/*
|
|
Crosshair
|
|
Author: Newton
|
|
|
|
Virtual cursor for gamepad controls
|
|
*/
|
|
|
|
local crew, angle, xpos, ypos, aiming, menu;
|
|
|
|
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()
|
|
{
|
|
SetVisibility(false);
|
|
xpos = ypos = 0;
|
|
aiming = false;
|
|
}
|
|
|
|
public func FxMoveTimer()
|
|
{
|
|
if (!crew)
|
|
{
|
|
RemoveObject();
|
|
return FX_Execute_Kill;
|
|
}
|
|
|
|
var target_angle = Angle(0,0,xpos,ypos)*10;
|
|
|
|
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);
|
|
if (Abs(angle_diff) < 450)
|
|
angle = angle + angle_diff / 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);
|
|
// Aim somewhere useful. Note that this can be overwritten by objects and isn't used for throwing.
|
|
angle = 800*(crew->GetDir()*2-1);
|
|
}
|
|
|
|
UpdatePosition();
|
|
crew->TriggerHoldingControl();
|
|
}
|
|
|
|
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)
|
|
{
|
|
var newvis, oldvis;
|
|
if (visible)
|
|
newvis = VIS_Owner;
|
|
else
|
|
newvis = VIS_None;
|
|
oldvis = this.Visibility;
|
|
this.Visibility = newvis;
|
|
return newvis != oldvis;
|
|
}
|
|
|
|
private func CreateMoveEffect(object clonk)
|
|
{
|
|
crew = clonk;
|
|
UpdatePosition();
|
|
RemoveEffect("Move",this);
|
|
AddEffect("Move",this,1,1,this);
|
|
}
|
|
|
|
public func StartAim(object clonk, int default_angle, object GUImenu)
|
|
{
|
|
aiming = true;
|
|
|
|
// gui or landscape mode:
|
|
if (GUImenu)
|
|
{
|
|
SetCategory(C4D_StaticBack | C4D_IgnoreFoW | C4D_Foreground | C4D_Parallax);
|
|
menu = GUImenu;
|
|
this["Parallaxity"] = [0,0];
|
|
}
|
|
else
|
|
{
|
|
SetCategory(C4D_StaticBack | C4D_IgnoreFoW);
|
|
menu = nil;
|
|
}
|
|
|
|
// Use the given angle if the player wasn't aiming before.
|
|
if (SetVisibility(true) && default_angle)
|
|
angle = default_angle;
|
|
|
|
CreateMoveEffect(clonk);
|
|
}
|
|
|
|
private func UpdatePosition()
|
|
{
|
|
var x = +Sin(angle,CURSOR_Radius,10);
|
|
var y = -Cos(angle,CURSOR_Radius,10);
|
|
|
|
if (menu)
|
|
SetPosition(menu->GetX()+x,menu->GetY()+y);
|
|
else
|
|
SetPosition(crew->GetX()+x,crew->GetY()+y);
|
|
|
|
crew->UpdateVirtualCursorPos();
|
|
}
|
|
|
|
private func MirrorCursor()
|
|
{
|
|
return;
|
|
angle = -Normalize(angle,-1800,10);
|
|
}
|
|
|
|
public func StopAim()
|
|
{
|
|
aiming = false;
|
|
}
|
|
|
|
// Aiming means that some object is currently actively using the crosshair.
|
|
public func IsAiming()
|
|
{
|
|
return aiming;
|
|
}
|
|
|
|
// The crosshair is also active when the player is holding the aiming stick.
|
|
public func IsActive()
|
|
{
|
|
return aiming || Visible();
|
|
}
|
|
|
|
public func Aim(int ctrl, object clonk, int strength, int repeat, int status)
|
|
{
|
|
// start (stealth) aiming
|
|
if(!GetEffect("Move",this))
|
|
CreateMoveEffect(clonk);
|
|
|
|
// aiming with analog pad
|
|
if (status == CONS_Moved &&
|
|
(ctrl == CON_AimAxisUp || ctrl == CON_AimAxisDown || ctrl == CON_AimAxisLeft || ctrl == CON_AimAxisRight))
|
|
{
|
|
if(ctrl == CON_AimAxisUp) ypos = -strength;
|
|
if(ctrl == CON_AimAxisDown) ypos = strength;
|
|
if(ctrl == CON_AimAxisLeft) xpos = -strength;
|
|
if(ctrl == CON_AimAxisRight) xpos = strength;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public func Direction(int ctrl)
|
|
{
|
|
if(!crew) return;
|
|
|
|
angle = Normalize(angle,-1800,10);
|
|
//Message("%d, %d",this,angle,ctrl);
|
|
if(ctrl == CON_Left)
|
|
if(angle > 0)
|
|
MirrorCursor();
|
|
|
|
if(ctrl == CON_Right)
|
|
if(angle < 0)
|
|
MirrorCursor();
|
|
|
|
return;
|
|
}
|