Merge branch 'gamepad-controls'

qteditor^2
Lukas Werling 2016-08-07 17:57:57 +02:00
commit f3b2ff1295
16 changed files with 272 additions and 391 deletions

View File

@ -108,6 +108,13 @@ protected func CatchBlow()
if (GetAction() == "Dead") return;
if (!Random(5)) PlaySoundHurt();
}
protected func OnEnergyChange(int change, int cause, int caused_by)
{
if (change < 0 && GetCursor(GetOwner()) == this)
PlayRumble(GetOwner(), Min(300 + 1000 * -change / this.MaxEnergy, 1000), 150);
return _inherited(...);
}
protected func Grab(object pTarget, bool fGrab)
{

View File

@ -169,8 +169,10 @@ public func OnRopeBreak()
/*-- Grapple rope controls --*/
public func FxIntGrappleControlControl(object target, proplist effect, int ctrl, int x, int y, int strength, repeat, release)
public func FxIntGrappleControlControl(object target, proplist effect, int ctrl, int x, int y, int strength, bool repeat, int status)
{
if (status == CONS_Moved) return false;
var release = status == CONS_Up;
// Cancel this effect if clonk is now attached to something.
if (target->GetProcedure() == "ATTACH")
{

View File

@ -33,6 +33,8 @@ public func IsDigging() { return is_digging; }
public func HoldingEnabled() { return true; }
public func DefaultCrosshairAngle(object clonk, int d) { return 900 * d; }
public func ControlUseStart(object clonk, int x, int y)
{
AddEffect("ShovelDig", clonk, 1, 1, this);

View File

@ -22,7 +22,15 @@ func Hit()
/*-- Usage --*/
public func ControlUse(object clonk, x, y)
public func DefaultCrosshairAngle(object clonk, int d)
{
// Easy mode for gamepad users: automatically boost a jump.
if (clonk->GetYDir() < -10)
return Angle(0, 0, -clonk->GetXDir(), -clonk->GetYDir(), 10);
return 0;
}
protected func ControlUse(object clonk, x, y)
{
if (!GetEffect("IntReload", this) && !GetEffect("IntBurstWind", this))
{
@ -251,4 +259,4 @@ local Name = "$Name$";
local Description = "$Description$";
local Collectible = true;
local MaxIntake = 30;
local Components = {Cloth = 1, Metal = 1};
local Components = {Cloth = 1, Metal = 1};

View File

@ -5,68 +5,85 @@
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;
// 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()
{
this["Visibility"] = VIS_None;
dirx = diry = xpos = ypos = 0;
SetVisibility(false);
xpos = ypos = 0;
aiming = false;
}
public func FxMoveTimer()
{
var speed = 0;
var dpad_rotatespeed = 35;
// dpad mode
if(diry)
if (!crew)
{
if (diry < 0) speed = -Sin(angle,100,10);
else if (diry > 0) speed = +Sin(angle,100,10);
angle += dpad_rotatespeed*speed/100;
UpdateAnalogpadPos();
RemoveObject();
return FX_Execute_Kill;
}
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 analog_strength = BoundBy(Sqrt(xpos*xpos+ypos*ypos),0,100);
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 (angle_diff == 0) angle_diff = 1;
angle = angle + angle_diff * analog_strength / 100 / 8;
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();
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);
ypos = Cos(angle/10,-100);
var newvis, oldvis;
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)
private func CreateMoveEffect(object clonk)
{
// only reinitialize angle if the crosshair hasn't been there before
if(!GetEffect("Move",this))
{
// which should basically be only the case on the first time aiming
angle = 800*(clonk->GetDir()*2-1);
}
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)
{
@ -79,22 +96,12 @@ public func StartAim(object clonk, bool stealth, object GUImenu)
SetCategory(C4D_StaticBack | C4D_IgnoreFoW);
menu = nil;
}
// set starting position for analog pad
UpdateAnalogpadPos();
crew = clonk;
UpdatePosition();
RemoveEffect("Move",this);
AddEffect("Move",this,1,1,this);
if(!stealth)
{
this["Visibility"] = VIS_Owner;
crew->SetComDir(COMD_Stop);
aiming = true;
EnableKeyAimControls(true);
}
// Use the given angle if the player wasn't aiming before.
if (SetVisibility(true) && default_angle)
angle = default_angle;
CreateMoveEffect(clonk);
}
private func UpdatePosition()
@ -112,65 +119,41 @@ private func UpdatePosition()
private func MirrorCursor()
{
return;
angle = -Normalize(angle,-1800,10);
UpdateAnalogpadPos();
}
public func StopAim()
{
RemoveEffect("Move",this);
this["Visibility"] = VIS_None;
dirx = 0;
diry = 0;
EnableKeyAimControls(false);
analogaim = 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);
}
// Aiming means that some object is currently actively using the crosshair.
public func IsAiming()
{
return aiming;
}
public func Aim(int ctrl, object clonk, int strength, int repeat, int release)
// 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))
StartAim(clonk,true);
CreateMoveEffect(clonk);
// 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_AimAxisDown) ypos = strength;
if(ctrl == CON_AimAxisLeft) 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 false;

View File

@ -46,6 +46,9 @@ static const ACTIONTYPE_EXTRA = 4;
// elevators within this range (x) can be called
static const ELEVATOR_CALL_DISTANCE = 30;
// default throwing angle used while the Clonk isn't aiming
static const DEFAULT_THROWING_ANGLE = 500;
/* ++++++++++++++++++++++++ Clonk Inventory Control ++++++++++++++++++++++++ */
/*
@ -178,13 +181,13 @@ public func GetExtraInteractions()
/* +++++++++++++++++++++++++++ Clonk Control +++++++++++++++++++++++++++ */
/* Main control function */
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
{
if (!this)
return false;
// Contents menu
if (ctrl == CON_Contents && !release)
if (ctrl == CON_Contents && status == CONS_Down)
{
// Close any menu if open.
if (GetMenu())
@ -221,10 +224,11 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
else ctrl = CON_Use;
repeat = true;
release = false;
status = CONS_Down;
}
// controls except a few reset a previously given command
else SetCommand("None");
else if (status != CONS_Moved)
SetCommand("None");
/* aiming with analog pad or keys:
This works completely different. There are CON_AimAxis* and CON_Aim*,
@ -238,23 +242,29 @@ 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
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
|| ctrl == CON_AimUp || ctrl == CON_AimDown || ctrl == CON_AimLeft || ctrl == CON_AimRight)
if (ctrl == CON_AimAxisUp || ctrl == CON_AimAxisDown || ctrl == CON_AimAxisLeft || ctrl == CON_AimAxisRight)
{
var success = VirtualCursor()->Aim(ctrl,this,strength,repeat,release);
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
return success && VirtualCursor()->IsAiming();
}
// Simulate a mouse cursor for gamepads.
if (HasVirtualCursor())
{
x = this.control.mlastx;
y = this.control.mlasty;
}
// save last mouse position:
// if the using has to be canceled, no information about the current x,y
// is available. Thus, the last x,y position needs to be saved
if (ctrl == CON_Use || ctrl == CON_UseAlt)
else if (ctrl == CON_Use || ctrl == CON_UseAlt)
{
this.control.mlastx = x;
this.control.mlasty = y;
}
var proc = GetProcedure();
// building, vehicle, mount, contents, menu control
@ -269,23 +279,23 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
// menu
if (this.control.menu)
{
return Control2Menu(ctrl, x,y,strength, repeat, release);
return Control2Menu(ctrl, x,y,strength, repeat, status);
}
var contents = this->GetHandItem(0);
// usage
var use = (ctrl == CON_Use || ctrl == CON_UseDelayed || ctrl == CON_UseAlt || ctrl == CON_UseAltDelayed);
var use = (ctrl == CON_Use || ctrl == CON_UseAlt);
if (use)
{
if (house)
{
return ControlUse2Script(ctrl, x, y, strength, repeat, release, house);
return ControlUse2Script(ctrl, x, y, strength, repeat, status, house);
}
// control to grabbed vehicle
else if (vehicle && proc == "PUSH")
{
return ControlUse2Script(ctrl, x, y, strength, repeat, release, vehicle);
return ControlUse2Script(ctrl, x, y, strength, repeat, status, vehicle);
}
else if (vehicle && proc == "ATTACH")
{
@ -301,25 +311,25 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
usage via CancelUse().
*/
if (ControlUse2Script(ctrl, x, y, strength, repeat, release, vehicle))
if (ControlUse2Script(ctrl, x, y, strength, repeat, status, vehicle))
return true;
else
{
// handled if the horse is the used object
// ("using" is set to the object in StartUse(Delayed)Control - when the
// ("using" is set to the object in StartUseControl - when the
// object returns true on that callback. Exactly what we want)
if (this.control.current_object == vehicle) return true;
// has been cancelled (it is not the start of the usage but no object is used)
if (!this.control.current_object && (repeat || release)) return true;
if (!this.control.current_object && (repeat || status == CONS_Up)) return true;
}
}
// releasing the use-key always cancels shelved commands (in that case no this.control.current_object exists)
if(release) StopShelvedCommand();
if(status == CONS_Up) StopShelvedCommand();
// Release commands are always forwarded even if contents is 0, in case we
// need to cancel use of an object that left inventory
if (contents || (release && this.control.current_object))
if (contents || (status == CONS_Up && this.control.current_object))
{
if (ControlUse2Script(ctrl, x, y, strength, repeat, release, contents))
if (ControlUse2Script(ctrl, x, y, strength, repeat, status, contents))
return true;
}
}
@ -327,7 +337,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
// A click on throw can also just abort usage without having any other effects.
// todo: figure out if wise.
var currently_in_use = this.control.current_object != nil;
if ((ctrl == CON_Throw || ctrl == CON_ThrowDelayed) && currently_in_use && !release)
if (ctrl == CON_Throw && currently_in_use && status == CONS_Down)
{
CancelUse();
return true;
@ -336,7 +346,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
// Throwing and dropping
// only if not in house, not grabbing a vehicle and an item selected
// only act on press, not release
if ((ctrl == CON_Throw || ctrl == CON_ThrowDelayed) && !house && (!vehicle || proc == "ATTACH" || proc == "PUSH") && !release)
if (ctrl == CON_Throw && !house && (!vehicle || proc == "ATTACH" || proc == "PUSH") && status == CONS_Down)
{
if (contents)
{
@ -365,33 +375,19 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
if (only_drop || Distance(0, 0, x, y) < 10 || (Abs(x) < 10 && y > 10))
only_drop = true;
// throw
if (ctrl == CON_Throw)
CancelUse();
if (only_drop)
return ObjectCommand("Drop", contents);
else
{
CancelUse();
if (only_drop)
return ObjectCommand("Drop", contents);
else
return ObjectCommand("Throw", contents, x, y);
}
// throw delayed
if (ctrl == CON_ThrowDelayed)
{
CancelUse();
if (release)
if (HasVirtualCursor() && !VirtualCursor()->IsActive())
{
VirtualCursor()->StopAim();
if (only_drop)
return ObjectCommand("Drop", contents);
else
return ObjectCommand("Throw", contents, this.control.mlastx, this.control.mlasty);
}
else
{
VirtualCursor()->StartAim(this);
return true;
var angle = DEFAULT_THROWING_ANGLE * (GetDir()*2 - 1);
x = +Sin(angle, CURSOR_Radius, 10);
y = -Cos(angle, CURSOR_Radius, 10);
}
return ObjectCommand("Throw", contents, x, y);
}
}
}
@ -402,14 +398,14 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
// forward to script...
if (house)
{
return ControlMovement2Script(ctrl, x, y, strength, repeat, release, house);
return ControlMovement2Script(ctrl, x, y, strength, repeat, status, house);
}
else if (vehicle)
{
if (ControlMovement2Script(ctrl, x, y, strength, repeat, release, vehicle)) return true;
if (ControlMovement2Script(ctrl, x, y, strength, repeat, status, vehicle)) return true;
}
return ObjectControlMovement(plr, ctrl, strength, release);
return ObjectControlMovement(plr, ctrl, strength, status);
}
// Do a roll on landing or when standing. This means that the CON_Down was not handled previously.
@ -433,7 +429,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
// Fall through half-solid mask
if (ctrl == CON_FallThrough)
{
if(!release)
if(status == CONS_Down)
{
if (this->IsWalking())
{
@ -469,7 +465,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
}
// Unhandled control
return _inherited(plr, ctrl, x, y, strength, repeat, release, ...);
return _inherited(plr, ctrl, x, y, strength, repeat, status, ...);
}
// A wrapper to SetCommand to catch special behaviour for some actions.
@ -617,18 +613,12 @@ func CanReIssueCommand(proplist data)
if(data.ctrl == CON_Use)
return !data.obj->~RejectUse(this);
if(data.ctrl == CON_UseDelayed)
return !data.obj->~RejectUse(this);
}
func ReIssueCommand(proplist data)
{
if(data.ctrl == CON_Use)
return StartUseControl(data.ctrl, this.control.mlastx, this.control.mlasty, data.obj);
if(data.ctrl == CON_UseDelayed)
return StartUseDelayedControl(data.ctrl, data.obj);
}
func StartUseControl(int ctrl, int x, int y, object obj)
@ -651,6 +641,17 @@ func StartUseControl(int ctrl, int x, int y, object obj)
this.control.using_type = DetermineUsageType(obj);
this.control.alt = ctrl != CON_Use;
if (HasVirtualCursor())
{
var cursor = VirtualCursor(), angle;
if (!cursor->IsActive() && (angle = obj->~DefaultCrosshairAngle(this, GetDir()*2 - 1)))
{
x = +Sin(angle, CURSOR_Radius, 10);
y = -Cos(angle, CURSOR_Radius, 10);
}
cursor->StartAim(this, angle);
}
var hold_enabled = obj->Call("~HoldingEnabled");
if (hold_enabled)
@ -687,37 +688,6 @@ func StartUseControl(int ctrl, int x, int y, object obj)
return handled;
}
func StartUseDelayedControl(int ctrl, object obj)
{
this.control.started_use = false;
if(obj->~RejectUse(this))
{
// remember for later:
ShelveCommand(this, "CanReIssueCommand", this, "ReIssueCommand", {obj = obj, ctrl = ctrl});
// but still catch command
return true;
}
// Disable climb/hangle actions for the duration of this use
if (obj.ForceFreeHands && !GetEffect("IntControlFreeHands", this)) AddEffect("IntControlFreeHands", this, 130, 0, this);
this.control.current_object = obj;
this.control.using_type = DetermineUsageType(obj);
this.control.alt = ctrl != CON_UseDelayed;
VirtualCursor()->StartAim(this);
// call UseStart
var handled = obj->Call(GetUseCallString("Start"),this,this.control.mlastx,this.control.mlasty);
this.control.noholdingcallbacks = !handled;
if(handled)
this.control.started_use = true;
return handled;
}
func CancelUseControl(int x, int y)
{
// forget possibly stored commands
@ -782,11 +752,6 @@ func HoldingUseControl(int ctrl, int x, int y, object obj)
{
var mex = x;
var mey = y;
if (ctrl == CON_UseDelayed || ctrl == CON_UseAltDelayed)
{
mex = this.control.mlastx;
mey = this.control.mlasty;
}
//Message("%d,%d",this,mex,mey);
@ -829,29 +794,6 @@ func HoldingUseControl(int ctrl, int x, int y, object obj)
return handled;
}
func StopUseDelayedControl(object obj)
{
// ControlUseStop, ControlUseAltStop, ContainedUseAltStop, etc...
var handled = obj->Call(GetUseCallString("Stop"), this, this.control.mlastx, this.control.mlasty);
if (!handled)
handled = obj->Call(GetUseCallString(), this, this.control.mlastx, this.control.mlasty);
if (obj == this.control.current_object)
{
VirtualCursor()->StopAim();
// see StopUseControl
if(handled != -1)
{
this.control.current_object = nil;
this.control.using_type = nil;
this.control.alt = false;
}
this.control.noholdingcallbacks = false;
}
return handled;
}
// very infrequent timer to prevent dangling effects, this is not necessary for correct functioning
func FxItemRemovalCheckTimer(object target, proplist effect, int time)
{
@ -876,43 +818,31 @@ func FxItemRemovalCheckStop(object target, proplist effect, int reason, bool tem
// Control use redirected to script
func ControlUse2Script(int ctrl, int x, int y, int strength, bool repeat, bool release, object obj)
func ControlUse2Script(int ctrl, int x, int y, int strength, bool repeat, int status, object obj)
{
// standard use
if (ctrl == CON_Use || ctrl == CON_UseAlt)
{
if (!release && !repeat)
if (status == CONS_Down && !repeat)
{
return StartUseControl(ctrl,x, y, obj);
}
else if (release && (obj == this.control.current_object || obj == GetActionTarget()))
else if (status == CONS_Up && (obj == this.control.current_object || obj == GetActionTarget()))
{
return StopUseControl(x, y, obj);
}
}
// gamepad use
else if (ctrl == CON_UseDelayed || ctrl == CON_UseAltDelayed)
{
if (!release && !repeat)
{
return StartUseDelayedControl(ctrl, obj);
}
else if (release && (obj == this.control.current_object || obj == GetActionTarget()))
{
return StopUseDelayedControl(obj);
}
}
// more use (holding)
if (ctrl == CON_Use || ctrl == CON_UseAlt || ctrl == CON_UseDelayed || ctrl == CON_UseAltDelayed)
if (ctrl == CON_Use || ctrl == CON_UseAlt)
{
if (release)
if (status == CONS_Up)
{
// leftover use release
CancelUse();
return true;
}
else if (repeat && !this.control.noholdingcallbacks)
else if (status == CONS_Down && repeat && !this.control.noholdingcallbacks)
{
return HoldingUseControl(ctrl, x, y, obj);
}
@ -922,7 +852,7 @@ func ControlUse2Script(int ctrl, int x, int y, int strength, bool repeat, bool r
}
// Control use redirected to script
func ControlMovement2Script(int ctrl, int x, int y, int strength, bool repeat, bool release, object obj)
func ControlMovement2Script(int ctrl, int x, int y, int strength, bool repeat, int status, object obj)
{
// overloads of movement commandos
if (ctrl == CON_Left || ctrl == CON_Right || ctrl == CON_Down || ctrl == CON_Up || ctrl == CON_Jump)
@ -931,7 +861,7 @@ func ControlMovement2Script(int ctrl, int x, int y, int strength, bool repeat, b
if (Contained() == obj)
control_string = "Contained";
if (release)
if (status == CONS_Up)
{
// if any movement key has been released, ControlStop is called
if (obj->Call(Format("~%sStop", control_string), this, ctrl))
@ -1040,7 +970,7 @@ func SetMenu(new_menu, bool unclosable)
SetComDir(COMD_Stop);
if (PlayerHasVirtualCursor(GetOwner()))
VirtualCursor()->StartAim(this,false, new_menu);
VirtualCursor()->StartAim(this, 0, new_menu);
else
{
if (GetType(new_menu) == C4V_C4Object && new_menu->~CursorUpdatesEnabled())

View File

@ -19,12 +19,12 @@ local virtual_cursor;
/* This part of gamepad control handles only object-style menus.
Fullscreen menus are handled differently. */
func Control2Menu(int ctrl, int x, int y, int strength, bool repeat, bool release)
func Control2Menu(int ctrl, int x, int y, int strength, bool repeat, int status)
{
/* all this stuff is already done on a higher layer - in playercontrol.c
now this is just the same for gamepad control */
if (!PlayerHasVirtualCursor(GetOwner()))
if (!HasVirtualCursor())
return true;
if (!this->GetMenu()) return false;
@ -36,27 +36,27 @@ func Control2Menu(int ctrl, int x, int y, int strength, bool repeat, bool releas
// update angle for visual effect on the menu
if (repeat)
{
if (ctrl == CON_UseDelayed || ctrl == CON_UseAltDelayed)
if (ctrl == CON_Use || ctrl == CON_UseAlt)
this->GetMenu()->~UpdateCursor(mex,mey);
}
// click on menu
if (release)
if (status == CONS_Up)
{
// select
if (ctrl == CON_UseDelayed)
if (ctrl == CON_Use)
this->GetMenu()->~OnMouseClick(mex,mey);
}
return true;
}
public func ObjectControlMovement(int plr, int ctrl, int strength, bool release)
public func ObjectControlMovement(int plr, int ctrl, int strength, int status)
{
// from PlayerControl.c
var result = inherited(plr,ctrl,strength,release,...);
var result = inherited(plr,ctrl,strength,status,...);
// do the following only if strength >= CON_Gamepad_Deadzone
if(!release)
if(status == CONS_Down)
if(strength != nil && strength < CON_Gamepad_Deadzone)
return result;
@ -66,7 +66,7 @@ public func ObjectControlMovement(int plr, int ctrl, int strength, bool release)
if(!virtual_cursor) return result;
// change direction of virtual_cursor
if(!release)
if(status == CONS_Down)
virtual_cursor->Direction(ctrl);
return result;
@ -79,7 +79,7 @@ func ReinitializeControls()
// if is aiming or in menu and no virtual cursor is there, create one
if (!virtual_cursor)
if (this.menu || this.control.current_object) // properties declared in ClonkControl.ocd
VirtualCursor()->StartAim(this,false,this.menu);
VirtualCursor()->StartAim(this,0,this.menu);
}
else
{
@ -91,6 +91,9 @@ func ReinitializeControls()
/* Virtual cursor stuff */
// Helper function.
private func HasVirtualCursor() { return PlayerHasVirtualCursor(GetOwner()); }
// get virtual cursor, if noone is there, create it
private func VirtualCursor()
{
@ -122,19 +125,12 @@ public func UpdateVirtualCursorPos()
public func TriggerHoldingControl()
{
// using has been commented because it must be possible to use the virtual
// cursor aim also without a used object - for menus
// However, I think the check for 'this.control.current_object' here is just an unecessary safeguard
// since there is always a using-object if the clonk is aiming for a throw
// or a use. If the clonk uses it, there will be callbacks that cancel the
// callbacks to the virtual cursor
// - Newton
if (/*this.control.current_object && */!this.control.noholdingcallbacks)
if (this.control.current_object && !this.control.noholdingcallbacks)
{
var ctrl = CON_UseDelayed;
var ctrl = CON_Use;
if (this.control.alt)
ctrl = CON_UseAltDelayed;
ObjectControl(GetOwner(), ctrl, 0, 0, 0, true, false);
ctrl = CON_UseAlt;
ObjectControl(GetOwner(), ctrl, 0, 0, 0, true, CONS_Down);
}
}
@ -143,4 +139,4 @@ func RemoveVirtualCursor()
{
if (virtual_cursor)
virtual_cursor->StopAim();
}
}

View File

@ -26,13 +26,13 @@ public func OnShiftCursor(object new_cursor)
return _inherited(new_cursor, ...);
}
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
{
if (!this)
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);
return inherited(plr, ctrl, x, y, strength, repeat, status, ...);
// Begin interaction.
if (ctrl == CON_Interact && !release)
if (ctrl == CON_Interact && status == CONS_Down)
{
this->CancelUse();
BeginInteract();
@ -50,7 +50,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
}
// Finish picking up (aka "collect").
if (ctrl == CON_Interact && release)
if (ctrl == CON_Interact && status == CONS_Up)
{
EndInteract();
return true;
@ -71,7 +71,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
}
}
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);
return inherited(plr, ctrl, x, y, strength, repeat, status, ...);
}
private func FxIntHighlightInteractionStart(object target, proplist fx, temp, proplist interaction, proplist interaction_help)

View File

@ -55,17 +55,17 @@ func RejectCollect(id objid, object obj)
return false;
}
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
{
if (!this)
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);
return inherited(plr, ctrl, x, y, strength, repeat, status, ...);
// Quickswitch changes the current active inventory slot
if (ctrl == CON_QuickSwitch && !release)
if (ctrl == CON_QuickSwitch && status == CONS_Down)
{
// but ignore quickswitch if we have more than 1 hand-slot
if(this.HandObjects > 1)
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);;
return inherited(plr, ctrl, x, y, strength, repeat, status, ...);;
// A number key (hotkey) is pressed, change quick switch slot
/*if (this.inventory.hotkey_down != nil)
@ -78,7 +78,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
SetHandItemPos(0, this.inventory.quick_slot); // quick_slot is updated in SetHandItemPos
return true;
}
if (ctrl == CON_QuickSwitch && release) // Do nothing for now but will be used in the future
if (ctrl == CON_QuickSwitch && status == CONS_Up) // Do nothing for now but will be used in the future
{
return true;
}
@ -86,7 +86,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
if (!Contained())
{
// Quick-pickup item via click? Note that this relies on being executed after the normal Clonk controls
if (ctrl == CON_Use && !this->GetHandItem(0) && !release)
if (ctrl == CON_Use && !this->GetHandItem(0) && status == CONS_Down)
{
var sort = Sort_Distance(x, y);
var items = FindAllPickupItems(sort);
@ -97,7 +97,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
}
// Begin picking up objects.
if (ctrl == CON_PickUp && !release)
if (ctrl == CON_PickUp && status == CONS_Down)
{
this->CancelUse();
BeginPickingUp();
@ -105,7 +105,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
}
// Drop the mouse item?
if (ctrl == CON_Drop && !release)
if (ctrl == CON_Drop && status == CONS_Down)
{
// Do not immediately collect another thing unless chosen with left/right.
if (this.inventory.is_picking_up)
@ -139,7 +139,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
}
// Finish picking up (aka "collect").
if (ctrl == CON_PickUp && release)
if (ctrl == CON_PickUp && status == CONS_Up)
{
EndPickingUp();
return true;
@ -223,7 +223,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
if (this.inventory.hotkey_down != nil && hot > 0 && hot <= this.MaxContentsCount && this.inventory.hotkey_down != hot)
{
// do nothing if this is just key down
if (!release)
if (status == CONS_Down)
return true;
// switch the two slots
this->~Switch2Items(this.inventory.hotkey_down-1, hot-1);
@ -240,7 +240,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
}
// hotkey up: perform slot selection
if (hot > 0 && hot <= this.MaxContentsCount && release)
if (hot > 0 && hot <= this.MaxContentsCount && status == CONS_Up)
{
// This wasn't liked by many players, so slot selection is back to key down.
@ -256,7 +256,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
return true;
}
// a hotkey is pressed, save it for now
if (hot > 0 && hot <= this.MaxContentsCount && !release)
if (hot > 0 && hot <= this.MaxContentsCount && status == CONS_Down)
{
this.inventory.hotkey_down = hot;
// For safety
@ -267,7 +267,7 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
return true;
}
return inherited(plr, ctrl, x, y, strength, repeat, release, ...);
return inherited(plr, ctrl, x, y, strength, repeat, status, ...);
}
private func FxIntHighlightItemStart(object target, proplist fx, temp, object item)

View File

@ -83,12 +83,12 @@ public func FxControlConstructionPreviewStart(object clonk, effect, int temp, id
}
// Called by Control2Effect
public func FxControlConstructionPreviewControl(object clonk, effect, int ctrl, int x, int y, int strength, bool repeat, bool release)
public func FxControlConstructionPreviewControl(object clonk, effect, int ctrl, int x, int y, int strength, bool repeat, int status)
{
if (ctrl != CON_Aim)
{
// CON_Use is accept, but don't remove the preview, this is done on releasing the button.
if (ctrl == CON_Use && !release)
if (ctrl == CON_Use && status == CONS_Down)
{
var ok = CreateConstructionSite(clonk, effect.structure, AbsX(effect.preview->GetX()), AbsY(effect.preview->GetY() + effect.preview.dimension_y/2), effect.preview.blocked, effect.preview.direction, effect.preview.stick_to);
if (ok)
@ -105,7 +105,7 @@ public func FxControlConstructionPreviewControl(object clonk, effect, int ctrl,
// (yes, this means that actionbar-hotkeys wont work for it. However clicking the button will.)
else if (IsInteractionControl(ctrl))
{
if (release)
if (status == CONS_Up)
effect.preview->Flip();
return true;
}

View File

@ -337,13 +337,13 @@ public func FxIntClimbControlStop(object target, effect fx, int reason, bool tmp
return FX_OK;
}
public func FxIntClimbControlControl(object target, effect fx, int ctrl, int x, int y, int strength, bool repeat, bool release)
public func FxIntClimbControlControl(object target, effect fx, int ctrl, int x, int y, int strength, bool repeat, int status)
{
// Only handle movement controls.
if (ctrl != CON_Up && ctrl != CON_Down && ctrl != CON_Right && ctrl != CON_Left)
return false;
// Perform actions on key down and not on release.
if (release)
if (status != CONS_Down)
return false;
// Move up and down by setting com dir.
if (ctrl == CON_Up)

View File

@ -21,9 +21,8 @@ global func IsMovementControl(int ctrl)
/** Control throws selected item */
global func IsThrowControl(int ctrl)
{
// left mouse button
if(ctrl == CON_Throw
|| ctrl == CON_ThrowDelayed)
// right mouse button
if(ctrl == CON_Throw)
return true;
return false;
@ -99,4 +98,4 @@ global func IsUseControl(int ctrl)
{
if (ctrl == CON_Use || ctrl == CON_UseAlt) return true;
return false;
}
}

View File

@ -18,12 +18,11 @@ global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int stren
{
var release = status == CONS_Up;
//Log("%d, %s, %i, %d, %d, %d, %v, %v", plr, GetPlayerControlName(ctrl), spec_id, x,y,strength, repeat, status);
if (status == CONS_Moved) return false;
// Control handled by definition? Forward
if (spec_id) return spec_id->ForwardedPlayerControl(plr, ctrl, x, y, strength, repeat, release);
if (spec_id) return spec_id->ForwardedPlayerControl(plr, ctrl, x, y, strength, repeat, status);
// Forward control to player
if (Control2Player(plr,ctrl, x, y, strength, repeat, release)) return true;
if (Control2Player(plr,ctrl, x, y, strength, repeat, status)) return true;
// Forward control to cursor
var cursor = GetCursor(plr);
@ -34,7 +33,7 @@ global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int stren
// menu controls:
if (cursor->~GetMenu())
if (cursor->~GetMenu() && status != CONS_Moved)
{
// direction keys are always forwarded to the menu
// (because the clonk shall not move while the menu is open)
@ -83,11 +82,11 @@ global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int stren
}
// Overload by effect?
if (cursor->Control2Effect(plr, ctrl, cursorX, cursorY, strength, repeat, release)) return true;
if (cursor->Control2Effect(plr, ctrl, cursorX, cursorY, strength, repeat, status)) return true;
if (cursor->ObjectControl(plr, ctrl, cursorX, cursorY, strength, repeat, release))
if (cursor->ObjectControl(plr, ctrl, cursorX, cursorY, strength, repeat, status))
{
if (cursor && !release && !repeat)
if (cursor && status == CONS_Down && !repeat)
{
// non-mouse controls reset view
if (!x && !y) ResetCursorView(plr);
@ -127,7 +126,7 @@ global func PlayerHasVirtualCursor(int plr)
// Control2Player
// Player-wide controls
global func Control2Player(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
global func Control2Player(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
{
// select previous or next
if (ctrl == CON_PreviousCrew)
@ -202,7 +201,7 @@ global func StopSelected(int plr)
// Control2Effect
// Call control function in all effects that have "Control" in their name
global func Control2Effect(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
global func Control2Effect(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
{
// x and y are local coordinates
if (!this) return false;
@ -213,7 +212,7 @@ global func Control2Effect(int plr, int ctrl, int x, int y, int strength, bool r
{
iEffect = GetEffect("*Control*", this, i);
if (iEffect)
if (EffectCall(this, iEffect, "Control", ctrl, x,y,strength, repeat, release))
if (EffectCall(this, iEffect, "Control", ctrl, x,y,strength, repeat, status))
return true;
}
// No effect handled the control
@ -224,7 +223,7 @@ global func Control2Effect(int plr, int ctrl, int x, int y, int strength, bool r
// Called from PlayerControl when a control is issued to the cursor
// Return whether handled
// To be overloaded by specific objects to enable additional controls
global func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
global func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
{
if (!this) return false;
@ -233,7 +232,7 @@ global func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
// Movement controls
if (ctrl == CON_Left || ctrl == CON_Right || ctrl == CON_Up || ctrl == CON_Down || ctrl == CON_Jump)
return ObjectControlMovement(plr, ctrl, strength, release, repeat);
return ObjectControlMovement(plr, ctrl, strength, status, repeat);
// Unhandled control
return false;
@ -276,7 +275,7 @@ global func NameComDir(comdir)
}
// Called when CON_Left/Right/Up/Down controls are issued/released
// Return whether handled
global func ObjectControlMovement(int plr, int ctrl, int strength, bool release, bool repeat)
global func ObjectControlMovement(int plr, int ctrl, int strength, int status, bool repeat)
{
if (!this) return false;
@ -284,13 +283,13 @@ global func ObjectControlMovement(int plr, int ctrl, int strength, bool release,
if (Contained()) return false;
// this is for controlling movement with Analogpad
if(!release)
if(status == CONS_Down)
if(strength != nil && strength < CON_Gamepad_Deadzone)
return true;
var proc = GetProcedure();
// Some specific movement controls
if (!release)
if (status == CONS_Down)
{
// Jump control
if (ctrl == CON_Jump)

View File

@ -37,8 +37,6 @@
#
# Gamepad controls
# -------------------------------------
# ThrowDelayed
# UseDelayed
# AimUp AimDown AimLeft AimRight
# AimAxisUp AimAxisDown AimAxisLeft AimAxisRight
#
@ -59,26 +57,6 @@
DefaultDisabled=1
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]
Identifier=AimAxisUp
GUIName=$CON_AimAxisUp$
@ -164,12 +142,6 @@
Hold=1
SendCursorPos=1
[ControlDef]
Identifier=ThrowDelayed
GUIName=$CON_Throw$
GUIDesc=$CON_Throw_Desc$
Hold=1
[ControlDef]
Identifier=Drop
GUIName=$CON_Drop$
@ -286,13 +258,6 @@
Hold=1
SendCursorPos=1
[ControlDef]
Identifier=UseDelayed
GUIName=$CON_Use$
GUIDesc=$CON_Use_Desc$
Hold=1
SendCursorPos=1
[ControlDef]
Identifier=UseAlt
GUIName=$CON_UseAlt$
@ -300,13 +265,6 @@
Hold=1
SendCursorPos=1
[ControlDef]
Identifier=UseAltDelayed
GUIName=$CON_UseAlt$
GUIDesc=$CON_UseAlt_Desc$
Hold=1
SendCursorPos=1
[ControlDef]
Identifier=CancelUse
@ -960,11 +918,54 @@
GUIGroup=40
Control=Interact
[Assignment]
Key=CON_Interact,CON_Left
Control=InteractNext_Left
Priority=75
[Assignment]
Key=CON_Interact,CON_Right
Control=InteractNext_Right
Priority=75
[Assignment]
Key=CON_Interact,CON_Up
Control=InteractNext_CycleObject
Priority=75
[Assignment]
Key=CON_Interact,CON_Down
Control=InteractNext_Stop
Priority=75
[Assignment]
Key=ControllerButtonX
Control=PickUp
GUIGroup=50
[Assignment]
Key=CON_PickUp,CON_Left
Control=PickUpNext_Left
[Assignment]
Key=CON_PickUp,CON_Right
Control=PickUpNext_Right
[Assignment]
Key=CON_PickUp,CON_Up
Control=PickUpNext_All
Priority=75
[Assignment]
Key=CON_PickUp,CON_Down
Control=PickUpNext_Stop
Priority=75
[Assignment]
Key=CON_PickUp,CON_Throw
Control=Drop
Priority=75
# Crew
[Assignment]
@ -985,13 +986,13 @@
GUIDesc=$KEY_GamepadUse_Desc$
GUIGroup=20
Priority=100
Control=UseDelayed
Control=Use
[Assignment]
Key=ControllerLeftTrigger
GUIGroup=20
Priority=100
Control=ThrowDelayed
Control=Throw
# TODO: Zoom
@ -1017,58 +1018,12 @@
Name=*_GamepadCon_*
[Assignment]
Key=CON_AimAxisLeft
Priority=50
Control=Left
[Assignment]
Key=CON_AimAxisRight
Priority=50
Control=Right
[Assignment]
Key=CON_AimAxisDown
Priority=50
Control=Down
[Assignment]
Key=CON_AimAxisUp
Priority=50
Control=Up
[Assignment]
Key=CON_Left
Priority=70
Control=AimLeft
[Assignment]
Key=CON_Right
Priority=70
Control=AimRight
[Assignment]
Key=CON_Down
Priority=70
Control=AimDown
[Assignment]
Key=CON_Up
Priority=70
Control=AimUp
[Assignment]
Key=CON_Down,CON_UseDelayed
Key=CON_Down,CON_Throw
GUIDisabled=1
GUIGroup=20
Priority=150
Control=Drop
[Assignment]
Key=CON_UseDelayed
GUIName=None
Priority=50
Control=ThrowDelayed
# ======================================================================= #
# Default mouse control #
# ======================================================================= #

View File

@ -2,13 +2,13 @@
#appendto Library_ClonkControl
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, int status)
{
if (!this)
return false;
// Spawn menu
if (ctrl == CON_SpawnMenu && !release)
if (ctrl == CON_SpawnMenu && status == CONS_Down)
{
// Close any menu if open.
if (GetMenu())
@ -31,5 +31,5 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
}
// Unhandled control will be handled by the library itself.
return _inherited(plr, ctrl, x, y, strength, repeat, release, ...);
}
return _inherited(plr, ctrl, x, y, strength, repeat, status, ...);
}

View File

@ -1,9 +1,9 @@
// Shows and hides the tutorial guide if the [H] button is pressed.
global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int strength, bool repeat, bool release)
global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int strength, bool repeat, int status)
{
if (ctrl != CON_TutorialGuide)
return _inherited(plr, ctrl, spec_id, x, y, strength, repeat, release, ...);
return _inherited(plr, ctrl, spec_id, x, y, strength, repeat, status, ...);
// Don't do anything if the player is a sequence.
if (GetActiveSequence())
return;
@ -17,4 +17,4 @@ global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int stren
else
guide->HideGuide();
return;
}
}