Wintermute Engine Forum
Wintermute Engine => Bug reports => Not a bug => Topic started by: Kaz on August 10, 2009, 06:37:36 PM
-
No complaint, this engine rocks, and nothing invented by humans can be perfect. Here is a weird one.
I have a script that does this:
else
{
Game.TakeItem("LetterRhiannon");
global gGotLetterRhiannon = true;
}
Rhiannon's letter goes to inventory as it should but occasionally - not on every playing - the global doesn't get set. The player complains that "the letter is still there". I have a savegame from a player to attest. I can see the letter in inventory, but the debugger tells me that the global is in a null state.
I believe I'm right that I can declare and set a global in the same statement, and the majority of times the game is played, both instructions are executed. It sounds like a bug, because usually it works and occasionally it doesn't.
Should I have used
else
{
Game.TakeItem("LetterRhiannon");
global gGotLetterRhiannon;
gGotLetterRhiannon = true;
}
instead, as a best practice principle anyway?
Cheers
Noel
-
I'm quite sure the problem is elsewhere. What is the *actual* code? It's in some event handler, I suppose, is there more code in the handler? Please post the exact script.
-
Mnem,
Thanks for having a look at this but I don't think there's any point sending any other code. There's only one place where the letter goes to inventory and there's only one place where the global gets set or not. The letter is in inventory, so it has to happen in that sequence. If the 'else' is entered, the letter gets taken, so the global should get set. But sometimes it's null.
Just one of those things I guess.
Suggest we classify it as 'can't reproduce'.
Noel
-
You should know that I usually have a good reason for asking the things I'm asking about.
And naturally, I can't diagnose or fix problems I don't have enough information about.
-
Acknowledged.
-
Acknowledged but still no info provided :-\
There are many factors that can affect this. For example, is your TakeItem method overridden? Does the handler with this code contain some "blocking" method, such as Talk, GoTo, PlayAnim?
Saying "hey! there's a bug but I won't tell you anything about it" is kind of... useless.
-
And judging by this thread (http://forum.dead-code.org/index.php?topic=2854.msg18012#msg18012) you are indeed using an overridden TakeItem() method. So one innocently looking line actually calls much more code under the hood. That's why knowing the context is extremely important when diagnosing "bugs"...
-
Mnem
I humbly and apologetically take your point. The overriding TakeItem from game.script:
method TakeItem(var ItemName)
{
// call the original method we have just overriden
this.TakeItem(ItemName);
global InventoryOn;
if(InventoryOn == true)
{
Game.PlaySound("sounds\ToInventory.ogg");
global InventoryHint = true;
Sleep(1000);
InventoryHint = false;
}
}
The full script where the method is called:
#include "scripts\base.inc"
#include "scripts\keys.inc"
self.GoExclusive();
on "LeftClick"
{
var a = Game.IsItemTaken("LetterRhiannon");
if(a == true)
{
Game.PlaySound("sounds\NoticeboardOn.ogg");
}
else
{
Game.TakeItem("LetterRhiannon");
global gGotLetterRhiannon = true;
}
self.Close;
Game.UnloadObject(this);
}
The script that checks whether the letter is in inventory as a condition on an action:
if(gFAC.Seen != true)
{
global gFireIsLit;
global gGotLetterRhiannon;
if(gFireIsLit != true || gGotLetterRhiannon != true)
{
// Fire not lit or study not visited - just rattle the door
Game.PlaySound("sounds\LockedSuffolkDoor.ogg");
gRhiannonHaunt.TriedDoor = true;
}
else
{
// Play the FAC sequence
Game.Interactive = false;
gRhiannonHaunt.Summon = false;
Game.PlaySound("sounds\LockedSuffolkDoor.ogg");
Sleep(1000);
Game.SetMousePos(1024, 768);
var video = Scene.GetNode("video");
video.Active = true;
video.PlayTheora("Video\FAC.ogg");
Sleep(20000);
video.Active = false;
// This gFAC.Seen = true will prevent the Summons from running again
gFAC.Seen = true;
gFAC.Solved = false;
Scene.InitializeDoor();
Game.Interactive = true;
}
}
Anything you can suggest as to why it works usually, but not always?
Thanks
-
Thanks :)
Now, what happens if the player clicks the window, and then, while the game is displaying the acquired item for one second, he clicks the window again? The LeftClick handler is executed again, it will find the item is already taken, so it will just play some sound and kill the window. Killing the window will also kill the original LeftClick handler, which is still executing the TakeItem line (waiting for one second) so it will never get to the second line.
A good practice is to enclose atomic actions invoked by player between Game.Interactive = false / true. That way the player cannot click again until the original click handler finishes.
-
Of course! Hemm, I mean, that sounds reasonable. No wonder you smiled :)
We'll test it.
Ah - double-clicked it as fast as I could. And it worked as it should. :(
Never mind, your suggestion sounds right, so we'll lock the routine down.
Thanks