Moving controls to script: Dig + Throw

stable-5.2
Sven Eberhardt 2009-06-15 22:48:53 -04:00
parent 943b47ebd5
commit f34c2d79bc
6 changed files with 210 additions and 425 deletions

View File

@ -204,8 +204,12 @@ bool C4PlayerControlAssignment::ResolveRefs(C4PlayerControlAssignmentSet *pParen
KeyComboItem &rKeyComboItem = *i;
if (rKeyComboItem.Key == KEY_Default && rKeyComboItem.sKeyName.getLength())
{
// this is a key reference - find it
C4PlayerControlAssignment *pRefAssignment = pParentSet->GetAssignmentByControlName(rKeyComboItem.sKeyName.getData());
// this is a key reference
// it may be preceded by CON_ to avoid ambigous keus
const char *szKeyName = rKeyComboItem.sKeyName.getData();
if (SEqual2(szKeyName, "CON_")) szKeyName +=4;
// - find it
C4PlayerControlAssignment *pRefAssignment = pParentSet->GetAssignmentByControlName(szKeyName);
if (pRefAssignment)
{
// resolve itself if necessary
@ -303,7 +307,8 @@ void C4PlayerControlAssignmentSet::MergeFrom(const C4PlayerControlAssignmentSet
for (C4PlayerControlAssignmentVec::const_iterator i = Src.Assignments.begin(); i != Src.Assignments.end(); ++i)
{
const C4PlayerControlAssignment &SrcAssignment = *i;
// overwrite if def of same name existed if it's not low priority anyway
// overwrite if def of same name existed if it's not low priority anyway?
// not so easy. Keys may be assigned to multiple controls and we may need to overwrite one or more of them...
C4PlayerControlAssignment *pPrevAssignment = GetAssignmentByControlName(SrcAssignment.GetControlName());
if (pPrevAssignment)
{
@ -333,7 +338,9 @@ C4PlayerControlAssignment *C4PlayerControlAssignmentSet::GetAssignmentByControlN
{
for (C4PlayerControlAssignmentVec::iterator i = Assignments.begin(); i != Assignments.end(); ++i)
if (SEqual((*i).GetControlName(), szControlName))
return &*i;
// We don't like release keys... (2do)
if (!((*i).GetTriggerMode() & C4PlayerControlAssignment::CTM_Release))
return &*i;
return NULL;
}

View File

@ -753,6 +753,13 @@ static bool FnSetActionData(C4AulContext *cthr, long iData, C4Object *pObj)
return TRUE;
}
static long FnGetActionData(C4AulContext *cthr, C4Object *pObj)
{
if (!pObj) pObj=cthr->Obj; if (!pObj || !pObj->Status) return FALSE;
// get data
return pObj->Action.Data;
}
static bool FnObjectSetAction(C4AulContext *cthr, C4Object *pObj, C4String *szAction,
C4Object *pTarget, C4Object *pTarget2, bool fDirect)
{
@ -6509,6 +6516,7 @@ void InitFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "Bubble", FnBubble);
AddFunc(pEngine, "SetAction", FnSetAction);
AddFunc(pEngine, "SetActionData", FnSetActionData);
AddFunc(pEngine, "GetActionData", FnGetActionData);
AddFunc(pEngine, "SetBridgeActionData", FnSetBridgeActionData);
AddFunc(pEngine, "GetAction", FnGetAction);
AddFunc(pEngine, "GetActTime", FnGetActTime);

View File

@ -2,12 +2,6 @@
#strict 2
// Zauberei - benötigt, wenn der Clonk Zielzauber z.B. aus dem Zauberturm zaubert
// Auch benötigt für den König
local pAimer; // Aktive Zielsteuerung; wird abgrbrochen, wenn der Zauberer gestört wird (Nur Fantasypack)
local pAimedSpell; // Zauber, der gezielt wird (Nur Fantasypack)
local pAimedSpellOrigin; // Objekt, das einen Zielzauber initiiert hat. An dieses werden SpellFailed/SpellSucceeded-Nachrichten weitergeleitet
/* Initialisierung */
@ -39,8 +33,6 @@ protected func Swimming2()
/* Bei Hinzufügen zu der Crew eines Spielers */
protected func Recruitment(int iPlr) {
// Alchemieregel: Jeder Clonk kriegt einen angelegten Beutel spendiert
if(ObjectCount(ALCO)) CreateObject(ALC_,0,0,-1)->~BelongTo(this);
// Broadcast für Crew
GameCallEx("OnClonkRecruitment", this, iPlr);
}
@ -70,82 +62,78 @@ public func FindTree()
return FindObject2(Find_AtPoint(), Find_OCF(OCF_Chop), Find_Layer(GetObjectLayer()));
}
/* Steuerung */
protected func ControlLeft()
public func GetInteractionTarget()
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlLeft")) return 1;
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlLeft(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlLeftDouble()
// Contained interaction target
var container = Contained();
if (container)
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlLeftDouble")) return true;
if (container->GetCategory() & (C4D_Structure | C4D_Vehicle)) return container;
}
// Procedure interaction target
// (Except for FIGHT, of course. You can't control your enemy ;))
var proc = GetProcedure();
if (proc == "PUSH" || proc == "PULL" || proc == "BUILD") return GetActionTarget();
// First contents object interaction target
return Contents(0);
}
protected func ControlRightDouble()
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
{
// Generic movement
if (inherited(plr, ctrl, x, y, strength, repeat, release)) return true;
var proc = GetProcedure();
// Handled by InteractionTarget?
var interaction_target = GetInteractionTarget();
if (interaction_target)
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlRightDouble")) return true;
if (interaction_target->ObjectControl(plr, ctrl, x,y, strength, repeat, release)) return true;
}
protected func ControlLeftReleased()
{
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlLeftReleased(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlRight()
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlRight")) return 1;
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlRight(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlRightReleased()
{
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlRightReleased(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlUp()
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlUp")) return 1;
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlUp(this);
// Bei JnR Delfinsprung
if(GetPlrCoreJumpAndRunControl(GetController()))
DolphinJump();
// Keine überladene Steuerung
return 0;
}
protected func ControlUpReleased()
{
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlUpReleased(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlUpDouble()
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlUpDouble")) return 1;
DolphinJump();
// Dolphin jump
if (ctrl == CON_DolphinJump) return DolphinJump();
// Context menu
else if (ctrl == CON_Context)
{
// Context menu of interaction target (fallback to this if no interaction target)
if (!interaction_target) interaction_target = this;
SetCommand(this,"Context",0,0,0,interaction_target);
return ExecuteCommand();
}
// Throw
else if (ctrl == CON_Throw)
{
// During Scale+Hangle, this means "Drop". During dig, this means object dig out request. Otherwise, throw.
if (proc == "DIG")
return SetActionData(!GetActionData());
else if (proc == "SCALE" || proc == "HANGLE")
return PlayerObjectCommand(plr, false, "Drop");
else
return PlayerObjectCommand(plr, false, "Throw");
}
// Dig
else if (ctrl == CON_Dig)
{
if (proc == "DIG")
{
// Currently, another press on dig ends digging. Maybe changed once we have the shovel system?
SetAction("Walk");
return true;
}
else if (proc == "WALK")
{
if (!GetPhysical("Dig")) return false;
if (!SetAction("Dig")) return false;
SetActionData(0);
return true;
}
// Can't dig now
return false;
}
// Unhandled
return false;
}
private func DolphinJump()
@ -166,105 +154,6 @@ private func DolphinJump()
SetAction("Dive");
}
protected func ControlDown()
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlDown")) return 1;
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlDown(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlDownReleased()
{
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlDownReleased(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlDownSingle()
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlDownSingle")) return 1;
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlDownSingle(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlDownDouble()
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlDownDouble")) return 1;
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlDownDouble(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlDig()
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlDig")) return 1;
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlDig(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlDigReleased()
{
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlDigReleased(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlDigSingle()
{
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlDigSingle(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlDigDouble()
{
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlDigDouble")) return 1;
// Steuerung an Pferd weiterleiten
if (IsRiding()) return GetActionTarget()->~ControlDigDouble(this);
// Keine überladene Steuerung
return 0;
}
protected func ControlThrow()
{
// Bei vorherigem Doppel-Stop nur Ablegen
if (GetPlrDownDouble(GetOwner())) return 0;
// Steuerung an Effekt weitergeben
if (Control2Effect("ControlThrow")) return 1;
// Reiten und Werfen
if (IsRiding())
if (Contents(0))
{
SetAction("RideThrow");
return 1;
}
// Keine überladene Steuerung
return 0;
}
protected func ControlUpdate(object self, int comdir, bool dig, bool throw)
{
// Steuerung an Pferd weiterleiten
if(IsRiding()) return GetActionTarget()->~ControlUpdate(self, comdir, dig, throw);
// Keine überladene Steuerung
return 0;
}
protected func ControlCommand(szCommand, pTarget, iTx, iTy, pTarget2, Data)
{
// Kommando MoveTo an Pferd weiterleiten
@ -291,6 +180,9 @@ protected func ControlCommand(szCommand, pTarget, iTx, iTy, pTarget2, Data)
return 0;
}
public func ControlDownDouble() {} // dummy
/* Verwandlung */
private func RedefinePhysical(szPhys, idTo)
@ -400,6 +292,7 @@ public func Redefine(idTo)
return 1;
}
/* Essen */
public func Feed(iLevel)
@ -409,6 +302,7 @@ public func Feed(iLevel)
return 1;
}
/* Aktionen */
private func Riding()
@ -501,6 +395,7 @@ protected func Scaling()
return 1;
}
/* Ereignisse */
protected func CatchBlow()
@ -542,9 +437,6 @@ protected func Death(int iKilledBy)
// Der Broadcast könnte seltsame Dinge gemacht haben: Clonk ist noch tot?
if (GetAlive()) return;
// den Beutel fallenlassen
if(GetAlchemBag()) GetAlchemBag()->~Loose();
Sound("Die");
DeathAnnounce();
// Letztes Mannschaftsmitglied tot: Script benachrichtigen
@ -583,6 +475,7 @@ protected func CheckStuck()
SetPosition(GetX(), GetY() + 1);
}
/* Status */
public func IsRiding()
@ -593,6 +486,7 @@ public func IsRiding()
public func IsClonk() { return 1; }
/* Kontext */
public func ContextRelease(pCaller)
@ -644,6 +538,7 @@ public func ContextHome(pCaller)
return 1;
}
/* Hilfsfunktion */
public func ContainedCall(string strFunction, object pTarget)
@ -653,34 +548,6 @@ public func ContainedCall(string strFunction, object pTarget)
AddCommand(this, "Enter", pTarget);
}
/* Steuerung */
protected func ControlSpecial2()
{
[$CtrlMenuDesc$|Image=CXTX]
// In einem Gebäude oder Fahrzeug: das Kontextmenü des Gebäudes öffnen
if (Contained())
if ((Contained()->GetCategory() & C4D_Structure) || (Contained()->GetCategory() & C4D_Vehicle))
{
SetCommand(this,"Context",0,0,0,Contained());
return ExecuteCommand();
}
// Fasst ein Objekt an: Kontextmenü des angefassten Objekts öffnen
if (GetAction() == "Push")
{
SetCommand(this,"Context",0,0,0,GetActionTarget());
return ExecuteCommand();
}
// Trägt ein Objekt: Kontextmenü des ersten getragenen Objekts öffnen
if (Contents(0))
{
SetCommand(this,"Context",0,0,0,Contents(0));
return ExecuteCommand();
}
// Ansonsten das Kontextmenü des Clonks öffnen
SetCommand(this,"Context",0,0,0,this);
return ExecuteCommand();
}
/* Callback beim Auswahl aus dem Construct-Kontextmenu */
@ -692,6 +559,7 @@ public func ControlCommandConstruction(target, x, y, target2, def)
return FinishCommand(this, false, 0) ;
}
/* Automatische Produktion */
public func ControlCommandAcquire(target, x, y, target2, def)
@ -751,6 +619,7 @@ public func GetProducerOf(def)
return FindObject2(Find_InRect(-500,-250,1000,500), Find_Func("IsProducerOf", this, def), Sort_Distance());
}
/* Trinken */
public func Drink(object pDrink)
@ -762,6 +631,7 @@ public func Drink(object pDrink)
// die Potions löschen sich meist selber...
}
/* Einsammeln */
public func RejectCollect(id idObject, object pObject)
@ -788,6 +658,7 @@ public func RejectCollect(id idObject, object pObject)
return GetNonSpecialCount()>=MaxContentsCount();
}
/* Itemlimit */
public func MaxContentsCount() { return 1; }
@ -884,24 +755,6 @@ public func DescendVehicle()
}
/* Effektsteuerung */
private func Control2Effect(string szControl)
{
// Von Effektzahl abwärts zählen
var i = GetEffectCount(0, this), iEffect;
var res;
while (i--)
{
// Effekte mit Control im Namen benachrichtigen
iEffect = GetEffect("*Control*", this, i);
// Message("%s", this, GetEffect(0, this, iEffect, 1));
if ( GetEffect(0, this, iEffect, 1) )
res += EffectCall(this, iEffect, szControl);
}
return res;
}
/* Pfeile */
@ -973,170 +826,8 @@ private func GetArrowCount()
}
/* Zauberei - benötigt, wenn der Clonk Zielzauber z.B. aus dem Zauberturm zaubert */
/* Dummies, damit die Engine die Namen kennt... */
public func SpellFailed(id idSpell, object pByCaller)
{
// Umleiten an eigentliche Zauberquelle? (Buch, Zauberturm, etc.)
var pSpellOrigin = pAimedSpellOrigin;
pAimedSpellOrigin = 0;
if (pSpellOrigin && pSpellOrigin != this)
// Auch bei nicht erfolgreicher Umleitung abbrechen: Das zaubernde Objekt hat im Normalfall die Zutaten/Zauberenergie für den
// Zauber bereit gestellt, und diese sollten nicht an den Clonk zurück gegeben werden
return (pSpellOrigin->~SpellFailed(idSpell, this));
// Magieenergie zurückgeben
DoMagicEnergy(Value(idSpell), 0, true);
// Alchemische Zutaten zurückgeben
if(ObjectCount(ALCO)) IncreaseAlchem(idSpell);
}
public func SpellSucceeded(id idSpell, object pByCaller)
{
// Umleiten an eigentliche Zauberquelle? (Buch, Zauberturm, etc.)
var pSpellOrigin = pAimedSpellOrigin;
pAimedSpellOrigin = 0;
if (pSpellOrigin && pSpellOrigin != this)
// Auch bei nicht erfolgreicher Umleitung abbrechen: Das zaubernde Objekt hat im Normalfall das Magietraining schon erledigt
return (pSpellOrigin->~SpellSucceeded(idSpell, this));
// Globaler Aufruf für Zauber
OnClonkSucceededSpell(idSpell);
}
// Der Clonk kann von sich aus nicht zaubern und hat keine Aktivitäten dafür
private func SetMagicAction(id idForSpell) {}
private func SetCastAction() {}
private func EndMagicAction() {}
/* Zielsteuerung - nur aktiv, wenn das Fantasypack die globalen Funktionen CreateAimer und CreateSelector überladen hat */
public func DoSpellAim(object pSpell, object pSpellOrigin)
{
pAimedSpell = pSpell;
pAimedSpellOrigin = pSpellOrigin;
pAimer = CreateAimer(this, this, GetDir()*180-90);
if (!pAimer) return 0;
// Callback an die Zauberquelle, dass noch gezielt wird
if (pSpellOrigin) pSpellOrigin->~SpellAiming(pSpell, this);
// Zielvorgang für Zauber
SetComDir(COMD_Stop);
SetCastAction();
return pAimer;
}
public func OnAimerEnter(int iAngle)
{
// Zauber weg?
if (!pAimedSpell) return OnAimerAbort(iAngle);
var idSpell = GetID(pAimedSpell);
// Aktivität
SetMagicAction();
// Zauber benachrichtigen
if (!pAimedSpell->~ActivateAngle(this, iAngle))
{
SpellFailed(idSpell);
return 0;
}
// OK; Zauber erfolgreich
return SpellSucceeded(idSpell);
}
public func AimingAngle(int iAngle)
{
// Zauber weg?
if (!pAimedSpell) return OnAimerAbort(iAngle);
// Zielaktion setzen, wenn im Laufen. Das ist etwas ungeschickt, weil damit
// die Magic-Aktion abgebrochen wird, die der Magier bereits bis zur Haelfte
// durchgefuehrt hat. Dummerweise laesst sich frueher nicht feststellen, ob
// der auszufuehrende Zauber einen Aimer brauchen wird...
if(GetActMapVal("Name", "AimMagic") )
if(GetAction() == "Walk" || GetAction() == "Magic")
SetAction("AimMagic");
// Phase anpassen
if(GetAction() == "AimMagic")
{
// Auch richtigen Winkel verwenden wenn nach links gedreht
var iHalfAngle = iAngle;
if(iHalfAngle < 0) iHalfAngle = -iHalfAngle;
SetPhase(BoundBy((iHalfAngle + 9) / 18, 0, 9) );
}
// Weitergabe an den Zauber
return pAimedSpell->~AimingAngle(this, iAngle);
}
public func OnAimerAbort(int iAngle)
{
// Aktivität zurücksetzen
EndMagicAction();
// Benachrichtigung
if (!pAimedSpell) return 1;
var idSpell = GetID(pAimedSpell);
if (!pAimedSpell->~AbortAiming(this))
// Standardaktion: Zauber löschen
RemoveObject(pAimedSpell);
pAimedSpell = 0;
// OK; Zauber nicht erfolgreich
return SpellFailed(idSpell);
}
public func DoSpellSelect(object pSpell, int iRadius, object pSpellOrigin)
{
// Zauber sichern
pAimedSpell = pSpell;
pAimedSpellOrigin = pSpellOrigin;
pAimer = CreateSelector(pSpell, this, iRadius);
if (!pAimer) return;
// Callback an die Zauberquelle, dass noch gezielt wird
if (pSpellOrigin) pSpellOrigin->~SpellAiming(pSpell, this);
// Zielvorgang für Zauber
SetComDir(COMD_Stop);
SetCastAction();
return pAimer;
}
public func OnSelectorEnter(object pTarget)
{
// Zauber weg?
if (!pAimedSpell) return OnAimerAbort();
var idSpell = GetID(pAimedSpell);
// Aktivität
SetMagicAction();
// Zauber benachrichtigen
if (!pAimedSpell->~ActivateTarget(this, pTarget))
{
SpellFailed(idSpell);
return 0;
}
// OK; Zauber erfolgreich
return SpellSucceeded(idSpell);
}
public func OnSelectorAbort()
{
// Aktivität zurücksetzen
EndMagicAction();
// Benachrichtigung
if (!pAimedSpell) return 1;
var idSpell = GetID(pAimedSpell);
if (!pAimedSpell->~AbortSelecting(this))
// Standardaktion: Zauber löschen
RemoveObject(pAimedSpell);
pAimedSpell = 0;
// OK; Zauber nicht erfolgreich
return SpellFailed(idSpell);
}
public func SelectorTarget(object pTarget) { if(pAimedSpell) return pAimedSpell->~SelectorTarget(this,pTarget); }
// Momentanen Zauber abbrechen
protected func AbortCasting()
{
if (pAimer) pAimer->Abort();
return 1;
}
public func Abort() {} // dummy call to instantiate function name
func Activate() {}
func HowToProduce() {}
func PackCount() {}

View File

@ -2,6 +2,7 @@
#strict 2
/* proplist changes aren't in this branch?
// stuff for the proplist changes
static const DFA_NONE =-1;
static const DFA_WALK = 0;
@ -28,18 +29,15 @@ global func GetActMapVal(string strEntry, string strAction, id idDef, int iEntry
if (!idDef) idDef = GetID();
if (strEntry == "Facet") strEntry = ["X", "Y", "Wdt", "Hgt", "OffX", "OffY"][iEntryNr];
return GetProperty(strEntry, GetProperty(strAction, idDef));
}
} */
global func CastC4ID(x) { return x; }
// Abgelöst durch SetPosition
global func ForcePosition(object obj, int x, int y) { return SetPosition(x, y, obj); }
// Abgelöst durch RemoveObject
global func AssignRemoval(object obj) { return RemoveObject(obj); }
// Für Szenarien ohne Objects.c4d...
global func EmptyBarrelID() { return BARL; }
global func GetBarrelType() {}
func BarrelDoFill() {}
func BarrelIsFull() {}
// Fügt das Material in ein Fass im Objekt ein
global func ObjectInsertMaterial(int imat, object pTarget)
@ -58,6 +56,7 @@ global func ObjectInsertMaterial(int imat, object pTarget)
// Kein Fass? Dann Objekt überlaufen lassen
return InsertMaterial(imat, GetX(pTarget)-GetX(), GetY(pTarget)-GetY());
}
// Auffüllbares Fass im Objekt suchen
global func FindFillBarrel(object pInObj, id type)

View File

@ -13,21 +13,47 @@ global func PlayerControl(int plr, int ctrl, id spec_id, int x, int y, int stren
if (spec_id) return spec_id->PlayerControl(plr, ctrl, x, y, strength, repeat, release);
// Forward control to cursor
var cursor = GetCursor(plr);
if (cursor) return cursor->ObjectControl(plr, ctrl, x,y, strength, repeat, release);
if (cursor)
{
// Object controlled by plr
cursor->SetController(plr);
// Overload by effect?
if (cursor->Control2Effect(plr, ctrl, x, y, strength, repeat, release)) return true;
return cursor->ObjectControl(plr, ctrl, x,y, strength, repeat, release);
}
// No cursor? Nothing to handle control then
return false;
}
/* Object functions */
// To be called in an object context only!
// Control2Effect
// Call control function in all effects that have "Control" in their name
global func Control2Effect(int ctrl, int x, int y, int strength, bool repeat, bool release)
{
// Count down from EffectCount, in case effects get deleted
var i = GetEffectCount("*Control*", this), iEffect;
var res;
while (i--)
{
iEffect = GetEffect("*Control*", this, i);
if ( GetEffect(0, this, iEffect, 1) )
if (EffectCall(this, iEffect, "Control", ctrl, x,y,strength, repeat, release))
return true;
}
// No effect handled the control
return false;
}
// ObjectControl
// 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)
{
// Object controlled by plr
SetController(plr);
// Any control resets a previously given command
SetCommand(this, "None");
// Movement controls
@ -36,9 +62,6 @@ global func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
return ObjectControlMovement(plr, ctrl, strength, release);
}
// Unhandled control
var srelease = "";
if (release) srelease="Up";
Log("Unhandled: %d, %s%s, %d, %d, %d, %v, %v", plr, GetPlayerControlName(ctrl), srelease, x,y,strength, repeat);
return false;
}
@ -108,9 +131,14 @@ global func ObjectControlUpdateComdir(int plr)
var is_handled;
var proc = GetProcedure();
if (proc == "WALK" || proc == "HANGLE" || proc == "PUSH" || proc == "PULL")
is_handled = (old_cx != new_cx) && !new_cy; // Only horizontal movement changed actual direction. Also, enfore clear Left/Right commands without leftover Up/Down
// Only horizontal movement changed actual direction
// Also, enfore clear Left/Right commands without leftover Up/Down
// CON_Down is never handled this way, thus forcing a CON_Stop
is_handled = (old_cx != new_cx) && !new_cy;
else if (proc == "SCALE")
is_handled = (old_cy != new_cy) && !new_cx; // Only vertical movement changed actual direction. Also, enfore clear Up/Down to prevent "Zuppel" in corner
// Only vertical movement changed actual direction
// Also, enfore clear Up/Down to prevent "Zuppel" in corner
is_handled = (old_cy != new_cy) && !new_cx;
else if (proc == "SWIM" || proc == "FLOAT" || proc == "DIG")
is_handled = (old_cx != new_cx || old_cy != new_cy); // Free 360 degree movement
else

View File

@ -1,5 +1,8 @@
[ControlDefs]
[ControlDef]
Identifier=None
[ControlDef]
Identifier=Left
GUIName=Left
@ -36,6 +39,16 @@
Identifier=Dig
GUIName=Dig
GUIDesc=Delve through the earth
[ControlDef]
Identifier=DolphinJump
GUIName=Dolphin Jump
GUIDesc=Jump out of the water while swimming
[ControlDef]
Identifier=Context
GUIName=Context menu
GUIDesc=Open context menu of current interaction target
@ -70,19 +83,19 @@
TriggerMode=Hold
[Assignment]
Key=A
Key=CON_Left
Control=Right
TriggerMode=Release | AlwaysUnhandled
Priority=5
[Assignment]
Key=A
Key=CON_Left
Control=Up
TriggerMode=Release | AlwaysUnhandled
Priority=-5
[Assignment]
Key=A
Key=CON_Left
Control=Down
TriggerMode=Release | AlwaysUnhandled
Priority=-5
@ -93,19 +106,19 @@
TriggerMode=Hold
[Assignment]
Key=D
Key=CON_Right
Control=Left
TriggerMode=Release | AlwaysUnhandled
Priority=5
[Assignment]
Key=D
Key=CON_Right
Control=Up
TriggerMode=Release | AlwaysUnhandled
Priority=-5
[Assignment]
Key=D
Key=CON_Right
Control=Down
TriggerMode=Release | AlwaysUnhandled
Priority=-5
@ -116,55 +129,94 @@
TriggerMode=Hold
[Assignment]
Key=S
Key=CON_Down
Control=Up
TriggerMode=Release | AlwaysUnhandled
Priority=5
[Assignment]
Key=S
Key=CON_Down
Control=Left
TriggerMode=Release | AlwaysUnhandled
TriggerMode=Release
Priority=-5
[Assignment]
Key=S
Key=CON_Down
Control=Right
TriggerMode=Release | AlwaysUnhandled
TriggerMode=Release
Priority=-5
[Assignment]
Key=CON_Down
Control=Down
TriggerMode=Release
Priority=-10
[Assignment]
Key=W
Control=Up
TriggerMode=Hold
[Assignment]
Key=W
Key=CON_Up
Control=Down
TriggerMode=Release | AlwaysUnhandled
Priority=5
[Assignment]
Key=W
Key=CON_Up
Control=Left
TriggerMode=Release | AlwaysUnhandled
Priority=-5
[Assignment]
Key=W
Key=CON_Up
Control=Right
TriggerMode=Release | AlwaysUnhandled
Priority=-5
[Assignment]
Key=CON_Dig
Control=Down
TriggerMode=Release | AlwaysUnhandled
Priority=5
[Assignment]
Key=CON_Dig
Control=Left
TriggerMode=Release | AlwaysUnhandled
Priority=5
[Assignment]
Key=CON_Dig
Control=Right
TriggerMode=Release | AlwaysUnhandled
Priority=5
[Assignment]
Key=CON_Dig
Control=Up
TriggerMode=Release | AlwaysUnhandled
Priority=5
[ControlSet]
Name=Keyboard2*
[Assignment]
Key=Q
Control=Throw
Priority=50
[Assignment]
Key=E
Control=Dig
Priority=50
[Assignment]
Key=Up,Up
ComboIsSequence=1
Control=DolphinJump
Priority=10
[Assignment]
Key=F
Control=Context