Nochmal bzgl. des Briefumschlags:
else if (UsedAction(eActLookAt))
{
Wait(5);
int state=Multi.Say("Oh, ein Briefumschlag.>Leer.>Immer noch leer.");
if (state==1) player.Animate(14, 3, eOnce, eBlock, eForwards);
if (state==1) aSound25.Play();
if (state==1) player.AddInventory(iBriefumschlag);
}
Die drei Zeilen mit if (state == 1) kann man zu einem Block zusammenfassen:
[ags] if (state==1) {
player.Animate(14, 3, eOnce, eBlock, eForwards);
aSound25.Play();
player.AddInventory(iBriefumschlag);
}[/ags]
Das Multiresponse-Modul ist ne feine Sache, es gibt aber eine eingebaute Funktion in AGS, die zumindest zwei states zulässt:
[ags] if (Game.DoOnceOnly("Briefkasten-Check")) {
player.Say("Oh, ein Briefumschlag!");
player.Animate(14, 3, eOnce, eBlock, eForwards);
aSound25.Play();
player.AddInventory(iBriefumschlag);
}
else player.Say("Er ist leer.");[/ags]
Den Text, der als Parameter übergeben wird, kannst Du beliebig wählen, er muss nur jeweils eindeutig sein. Damit kann man praktischerweise auch den gleichen Check an zwei verschiedenen Stellen im Code durchführen, indem man einfach bei beiden den selben Text verwendet.
So kann man zumindest vermeiden, wegen jedem Pups ne Raum- oder globale Variable einzuführen.
Wegen des Benutzens zweier Inventargegenstände:
Eigentlich sollte ein Inventargegenstand bei angewähltem "Benutze" nur sofort allein benutzt werden, wenn am Ende ein ">u" hängt.
Ich hab das mal mit dem ManiacMansion-Starterpack getestet.
Damit ein Inventargegenstand nicht auswählbar ist, sondern sofort benutzt wird, muss erstens ein ">u" am Namen hängen, zweitens muss eine Funktion bei "Interact with item" verlinkt sein, und drittens muss "Gehe zu" oder "Nimm" das aktive Verb sein.
Die ersten beiden Kriterien kannst Du ganz leicht ändern.
Als nächstes solltest Du bei "Use inventory on item" Folgendes eintragen:
[ags]function iBriefumschlag_UseInv()
{
if (player.ActiveInventory == iSkalpell) brief_oeffnen();
else Unhandled_Inventory();
}
function iSkalpell_UseInv()
{
if (player.ActiveInventory == iBriefumschlag) brief_oeffnen();
else Unhandled_Inventory();
}[/ags]
Über(!) diese beiden Funktionen setzt Du nun:
[ags]function brief_oeffnen() {
...
}[/ags]
Und schreibst dort rein, was passiert, wenn man das Skalpell mit dem Umschlag oder umgekehrt benutzt.
Einen Inventargegenstand mit einem Objekt oder Hotspot zu benutzen, funktioniert so:
Du legst für den Hotspot die "Any click on" funktion an, und dann setzt Du Folgendes rein:
[ags]function hBaum_AnyClick()
{
if (UsedAction(eActLookAt)) {
player.FaceLocation(176, 130);
Wait(5);
player.Say("Nur ein Baum.");
return; // jetzt aussteigen
}
if (MovePlayer(176, 155) == 2) {
player.FaceDirection(eDirUp);
Wait(5);
if (UsedAction(eActUseInventory)) {
if (player.ActiveInventory == iTaschenlampeOn) {
player.Say("Ich leuchte mal in den Baum.");
}
// else if (UsedAction()) { } // hier andere Verben
else Unhandled();
}
else Unhandled();
}
else player.Say("Ich komme nicht ran.");
}[/ags]
Hier lasse ich bei "Schau an" den Charakter nicht hinlaufen, d.h. er kann sich den Baum auch von der Ferne ansehen, falls er z.B. gerade nicht erreichbar ist. Soll er statt dessen genauer untersucht werden, setze ich den if (UsedAction(eActLookAt))-Block mit rein zu den anderen Verben.
MovePlayer liefert nur 2 zurück, wenn der Charakter auch tatsächlich bei den Koordinaten angekommen ist. Deswegen sollte man immer diesen == 2 Check machen.
Als nächstes lässt man den Charakter in die richtige Richtung schauen, dann überprüft man die Aktion, in diesem Fall muss also eActUseInventory verwendet werden. Am Ende überprüft man das verwendete Item.
Die Unhandled()s sind wichtig, damit das Spiel korrekt reagiert, falls eine andere Aktion oder ein anderes Item verwendet wurde.
Übrigens wirst Du auf Dauer nicht um globale oder zumindest Raumvariablen herumkommen; wie anders soll Dein Spiel wissen, wann der Spieler Fortschritte bei den Rätseln gemacht hat?
Ein paar Schlauköpfe haben das teilweise mit unsichtbaren Inventory Items und ähnlichen Späßen versucht, aber bitte begib Dich nicht auf derartige Irrwege.