Hi guys.
I've got a nasty bug in my script, totally my fault but I can't really solve it. (And it's going to be hard to explain the whole situation).
(deep breath)
When I call the function that "switch" characters (Basically a lot of status checking followed by .SetAsPlayer() ) if the mouse is over my makeshift inventory gui (Original Maniac Mansion /Zak style) the game crashes for "null pointer" reason.
(Yay ! I did it!)
My makeshift inventory is already under heavy brackets to avoid related "null pointer" issues :
(And most of it are managed in the standard Rep_execute function)
It won't work :
- If slot under the mouse == empty (and other "null string" issues)
- If the game is paused
- If the interface is hidden (like it's the case during the cutscenes / switches)
- If the mouse is not visible
- If there's a Communist uprising in Arizona
So... any clues of what it can be ?
How (when) is the Iventory windows populated when setAsPlayer() is called ?
Any clues of what can be the problem.
(I'll feel stupid if I call an artificial mouse position changing during switch)
Thanks a lot. (As again, sorry for the syntax)
Geoff ! Sorry for the late reply, thanks to have tried an answer.
(Sorry for the double post, but I just want to reformulate my problem)
1 - Is the Repeatedly Execute() from the main script an be activated Before FadeIn ? (As far as I understand AGS : never)
2 - Is the Repeatedly Execute() from the main script activated during SetAsPlayer() if performing its own task ?
3a) - What .SetAsPlayer internally does ?
3b) - In which order ?
3c) - Is there some of these tasks (like populating the inventory with the new character's possessions) are done Non_BLocking and/or AfterFadein ?
I guess this will sum up a possible path of solution.
Thanks again for the answers.
repeatedly_execute() only runs while the interface is enabled. During blocking events or fading in/out rooms, it doesn't.
I imagine SetAsPlayer()
-changes which character the player pointer points to
-if the other player is in a different room, performs a room change
Could you post your code? It's pretty much impossible to address your problem without knowing what you're doing.
We need to at least see the line in which the error occurs and the surrounding ones.
All I can say is that avoiding a null pointer error is usually really easy. Just put if (whatever != null) in front of the offending statement.
Here we go :
(Took myself time to translate comments)
The bug is always on line 83 After a Set as Player() if and olny if the mouse is somewhere over my make shif inventory...
I dunno, it's really like if the Inventory is not enabled before_fadein... (But I may be blatantly wrong)
Thanks again Kris, and good luck understanding my messy code.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
function repeatedly_execute() {
if (IsGamePaused() == 1) return;
String wScreen = "";
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// TIMER FUN - CASE 1 : AIR BREATHING
if (IsTimerExpired(6))
{
player.Mess("I can't breathe.");
STATUS_CANTBREATH++;
if (STATUS_CANTBREATH > 5)
{
Black();
player.Mess("AAAAAAAAAAAAAAAAAAAAARGH.");
player.ChangeRoom(290); // Temporary Death Room
return; //(I know it's useless but it makes me feel happy)
}
else
{
// NB : SEE ALSO Room 140
if (STATUS_Helmet == 1 && STATUS_Wet == 1)
{
STATUS_CANTBREATH = 0; // reset
player.Mess("Humpf ahhhh.");
player.Mess("I feel much better now!");
}
else
{
SetTimer(6, 120);
}
}
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// TIMER FUN - CASE 2 : JUNGLE REMOVAL ROUTINE
if (IsTimerExpired(8) && FLAG_JUNGLE_DISP == 1)
{
mAliens.Stop();
BlackOUT(1);
cZak.StopMoving(); // sinon c laid
Wait(60);
//*********************
SWITCH = 124;
//*********************
player.ChangeRoom(120); // Go directly to Mayan Temple
return; //(I know it's useless but it makes me feel happy)
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++ STANDARD LUCASARTS MANAGEMENT ++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++ 1 - INVENTORY BUTTON ON/OFF ACCORDING TO NUMBER OF ITEMS
if (gVerbs.Visible == true && mouse.Visible == true)
{
if (hidenINV.TopItem > 0) bINV_UP.Visible = true;
else bINV_UP.Visible = false;
if ((hidenINV.TopItem + 4) > (hidenINV.ItemCount-1))bINV_DOWN.Visible = false;
else bINV_DOWN.Visible = true;
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++ 2 - UPDATE INVENTORY LABELS
if (hidenINV.ItemCount>0) lINV_1HG.Text = hidenINV.ItemAtIndex[hidenINV.TopItem].Name;
else lINV_1HG.Text ="";
if (hidenINV.ItemCount>1 && (hidenINV.TopItem+1 <hidenINV.ItemCount)) lINV_2HD.Text = hidenINV.ItemAtIndex[hidenINV.TopItem+1].Name;
else lINV_2HD.Text ="";
if (hidenINV.ItemCount>2 && (hidenINV.TopItem+2 < hidenINV.ItemCount)) lINV_3BG.Text = hidenINV.ItemAtIndex[hidenINV.TopItem+2].Name;
else lINV_3BG.Text ="";
if (hidenINV.ItemCount>3 && (hidenINV.TopItem+3 < hidenINV.ItemCount)) lINV_4BD.Text = hidenINV.ItemAtIndex[hidenINV.TopItem+3].Name;
else lINV_4BD.Text ="";
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++ 3 - UPDATE INVENTORY LABELS COLOR + DATA ACCORDING TO MOUSE POSITION
if (gVerbs.Visible == true)
{
// PUT EVERYTHING PINK BY DEFAUT
lINV_1HG.TextColor = C64Pink;lINV_2HD.TextColor = C64Pink;
lINV_3BG.TextColor = C64Pink;lINV_4BD.TextColor = C64Pink;
lACTION.TextColor = C64Pink;
// LEFT COLUMN
if (mouse.x < bINV_UP.X)
{
if (mouse.y > gVerbs.Y+bINV_3BG.Y){
lINV_3BG.TextColor = C64Jaune;
wScreen = lINV_3BG.Text;}
else if (mouse.y > gVerbs.Y+bINV_1HG.Y){
lINV_1HG.TextColor = C64Jaune;
wScreen = lINV_1HG.Text;}
}
// RIGHT COLUMN
else if (mouse.x > bINV_UP.X+bINV_UP.Width)
{
if (mouse.y > gVerbs.Y+ bINV_3BG.Y){
lINV_4BD.TextColor = C64Jaune;
wScreen = lINV_4BD.Text;}
else if (mouse.y > gVerbs.Y+bINV_1HG.Y){
lINV_2HD.TextColor = C64Jaune;
wScreen = lINV_2HD.Text;}
}
}
//********************************************************
// TO THAT POINT IF THERE'S NULL TRANSFORM IT TO ""
if (wScreen == null) wScreen = ""; // THIS IS ANTI-BUG
//********************************************************
// ACTION LABEL COLOR : PURELY ESTHETICAL
if (mouse.y >= gActionLine.Y && mouse.y <= gActionLine.Y+gActionLine.Height)lACTION.TextColor = C64Jaune;
else lACTION.TextColor = C64Pink;
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// NO PUT ON / TAKE OFF FROM ANYTHING ABOVE ACTION LINE
if ((vACTION == aPutOn || vACTION ==aTakeOff) && mouse.y < gActionLine.Y)wScreen = " ";
// IF wScreen was not already fill with an inventory name - Fill it With the sceen Location
if (wScreen == "")wScreen = Game.GetLocationName(mouse.x, mouse.y);
// EXCEPTIOn - NO BOOK TITLE FOR ZAK
if (player.ID == cZak.ID && (player.Room == 10 || player.Room == 9))
{
if (GetLocationType(mouse.x, mouse.y) == eLocationHotspot)
{
LeSpot = Hotspot.GetAtScreenXY(mouse.x, mouse.y);
if (LeSpot.GetProperty("ISBOOK") > 0) wScreen = "books";
}
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++ Update ACTION LINE
// +++ CASE 1 - USE / GIVE
if (player.ActiveInventory != null)
{
if (vACTION == aGive)
{
if (GetLocationType(mouse.x, mouse.y) != eLocationCharacter) wScreen ="";
lACTION.Text = String.Format("%s %s to %s",wACTION, player.ActiveInventory.Name, wScreen);
}
// +++ AUTOMATICAL INVENTORY LAUCHES (NO "USE X WITH Y" FOR THOSE)
else if (vACTION == aUse && player.ActiveInventory == iGPS){iGPS.RunInteraction(eModeInteract);}
else if (vACTION == aUse && player.ActiveInventory == iRemoteC){iRemoteC.RunInteraction(eModeInteract); }
else if (vACTION == aUse && player.ActiveInventory == iMuffin) {iMuffin.RunInteraction(eModeInteract);}
// +++ STANDARD USE OF "USE"
else if (vACTION == aUse)
{
lACTION.Text = String.Format("%s %s with %s",wACTION, player.ActiveInventory.Name, wScreen);
}
// STANDARD USE OF ANY OTHER VERBS ON ITEMS
else
{
lACTION.Text = String.Format("%s %s",wACTION, player.ActiveInventory.Name);
}
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// NO INVENTORY THEREFORE IT'S ON THE SCREEN
else
{
lACTION.Text = String.Format("%s %s",wACTION, wScreen);
}
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++