⌂ YolkfolkThe Dizzy Fansite
Community discussion

DizzyAGE General Coding Queries

Started by delta on 9 February 2008 • 258,915 views

721 posts
#81397

Or make them all smaller tiles and stretch them over each 'room' with separate IDs and make a function that lists and enables them (and another to disable) and set the function to activate with a single command (or collider). That way one command will set them all in motion without having to faff around using room updates.

func MakeRain()
{
ObjSet(ObjFind(1000), O_DISABLE, 0);
ObjSet(ObjFind(1001), O_DISABLE, 0);
ObjSet(ObjFind(1002), O_DISABLE, 0);
}

func StopRain()
{
ObjSet(ObjFind(1000), O_DISABLE, 1);
ObjSet(ObjFind(1001), O_DISABLE, 1);
ObjSet(ObjFind(1002), O_DISABLE, 1);

func ActionObject_99()
{
if (ObjGet(ObjFind(99), O_STATUS) == 0)
{
Message1 (5,2, ""You press the button and it starts to rain"");
MessagePop();
ObjSet(ObjFind(99), O_STATUS, 1);
MakeRain();
return;
}
if (ObjGet(ObjFind(99), O_STATUS) == 1)
{
Message1 (5,2, ""You press the button again and it stops raining"");
MessagePop();
ObjSet(ObjFind(99), O_STATUS, 0);
StopRain();
}
}
👍 0
#81398

Nice one! That will be much easier. I'd assumed that since it can't enable an object spanning 5 screens, it also can't enable an object 5 screens away. Of course, many puzzles would be a pain in the arse if this were true :smile: .

Thanks both of you!

👍 0
#81507
Jamie pointed out that he could still use the 'space' key to make Dizzy jump up in my game Hush even though I'd set the game define 'SUPPORT_JUMPUP' to zero in the gamedef.gs file. The only reference to setting keys I can find is in the configuration settings file (where you set the dev mode off and on) but doesn't seem to make any difference when you disable any of the keys mentioned.

Does anybody know how to stop the 'space' bar acting as a jump key?
👍 0
#81508
How about turning on the custom movement and modifying the CM_EnterKeyState() function. I think you'd just have to delete the bit involving if(GetKey(KEY_JUMP))
👍 0
#81511
Thanks Simon, that gives me something to check out and play around with ...didn't want to play around with the Handler file as I still need the PlayerEnterJump function for when Dizzy lands on the fountain from the cracked water pipe. ...sigh, all this effort for such a small game.
👍 0
#81512
Well, that didn't work at all. It appears that all the functions involving jumping connect with the 'up' key which is probably why you can disable it in the Gamedef file by using '0' for SupportJumpUp as a general define for the DizzyAge engine to ignore any function that involves jumping.

Deleting all the 'up' and 'jump' key defines in the 'input' section of the Dizzy Configuration Settings file also has no effect.

I'm totally stumped!!
👍 0
#81513

Hi Steve,

I've tried it out and it definitely works. You just have to replace the CM_EnterKeyState() function with the following:

func CM_EnterKeyState()
{
if( PlayerGet(P_LIFE)<=0 ) { CM_EnterIdle(); return; } // prepare to die dir = 0; if( GetKey(KEY_RIGHT) ) dir++; if( GetKey(KEY_LEFT) ) dir--; if(dir!=0) { CM_EnterWalk(dir); } else { CM_EnterIdle(); } }

You also have to remove the ////'s from these lines in the PlayerUpdate handler. :wink:

PlayerSet(P_CUSTOMMOVE,1);
CM_Update();
👍 0
#81514
Thanks for having a look Simon. I'd already amended the func CM_EnterKeyState() to what you've put, but not any of the handler update functions. I couldn't find those lines in the PlayerUpdate part of the Handlers file, but my Handlers 'template' is a bit different to the standard as it includes Dizzy climbing (CM = 1, activate climbing code) and running (CM = 2, activate running code).

But it did prompt me to check out the rest of the handler file and found that if I deleted the last two lines in the func HandlerJump() coding so that the ScrSetHandlerData doesn't return a jump power to activate the jump, then the space key doesn't activate the jump code, and, more importantly, doesn't affect the 'PlayerEnterJump' coding for when Dizzy lands on the 'fountain of water'.

Thanks for all your help.
👍 0
#81645

Andy, ensuring the player picks up a diamond (or other 'coin') before solving the puzzle needed to reach it is not a big problem and a lot easier than faffing around making map changes.

Give the diamond a ID number and intially set it as an action object with a status of '0'. Then use the following code to action it:

func ActionObject_100()
{
idx = ObjFind(100);
ObjSet(idx, O_STATUS, 1);
ObjSet(idx, O_CLASS, 5);
ObjPresent(idx);
PickupObject(idx);
}

You have to use 'ObjPresent' as a game refresh for a dynamic object. You don't have to use 'DoPickupObject' as the engine doesn't check for a full inventory with a coin/diamond. Also even though it's picked up, the engine will still recognise the 'status'.

Then when giving the compass to the Viking you can use the status of the diamond as a check.

func UseObject_1000(idx) //viking
{
if (ObjGet(ObjFind(100), O_STATUS) == 0)
{
Message1 (5,2, ""I can't see that, the diamond above me is shining in my eyes"");
MessagePop();
return;
}
if (idx == ObjFind(1001)) //compass
{
InventorySub(idx);
Message1 (5,2, ""Thanks. Cheerio"");
MessagePop();
ObjSet(ObjFind(1000), O_DISABLE, 1);
return;
}
else
{
Message1 (5,2, ""I don't need that"");
MessagePop();
}}

So, as long as the diamond hasn't been picked up, he won't accept any object. As the check is in the UseObject function, you can still use the ActionObject function first for general information.

👍 0
#81647

That's great Grandad, thanks a lot! Good idea for the dialogue was well, I'll probably just copy that verbatim when the time comes to update. I'll update the map as you said, too. You can definitely be my play tester for the next game if I make one :smile: (and if you feel like it, of course!)

👍 0
#81653
...as long as you remember to enable the shield (I left that out of the code). Don't mind helping test your next game, even the early parts rather than a fully completed game - which is the way I generally do my games as it's easier to fix small parts as you go along (currently working on a section of a new game where lots of things change between night and day). My email address is in the readme file of all my games.
PS - I'll probably nick your 'costume change' coding in the future, as the idea of a game with lots of costume changes for different situations is very appealing.
👍 0
#81656

[quote data-userid="279" data-postid="81653"]

…as long as you remember to enable the shield (I left that out of the code). Don’t mind helping test your next game, even the early parts rather than a fully completed game – which is the way I generally do my games as it’s easier to fix small parts as you go along (currently working on a section of a new game where lots of things change between night and day). My email address is in the readme file of all my games.
PS – I’ll probably nick your ‘costume change’ coding in the future, as the idea of a game with lots of costume changes for different situations is very appealing.

[/quote]

Wow, that's amazing that I've been able to show one of the seasoned veterans something they can use! (Though I can't take all the credit.) To be honest, I wasn't sure if anyone would even notice that costume, since by that point players will most likely be keeping the scuba on. It was days of noodle-scratching to work costumes out, and hours of drawing, so I'm glad it's been of some use. In the update, I guess I'll deny access to the hotel if the player has the fancy clothes AND the scuba. Just to show off my drawing, haha.

👍 0
#81747

woo I've just written some new generic functions enabling me to call multi-choice questions (rather than just Yes/No questions), with up to 5 options. :smile:

could make things interesting... :teethy:

I've just been reading through this thread, and came across this from about 4 years ago. It occurs to me that I never actually used the code, although from what I remember it worked perfectly. Therefore, I thought I'd outline it below, for others to use if they wish.

Please bear in mind that I wrote this four years ago and have barely looked at it since. It's therefore a little fuzzy as to what it all does.

In def.gs:

tab questtab
tab answertab
tab actiontab

int totquest

The above defines the question 'tables' and an integer.

In dialogs.gs:

str g_op1;
str g_op2;
str g_op3;
str g_op4;
str g_op5;
str g_op6;
str g_op7;
str g_op8;
str g_op9;
int g_opt;
/////////////////////////////////////////////////////////////////////////////////
// IN: int; options; number of answer options
// IN: int; default=0; default selected answer
// IN: str; text; question text
// [IN]: str; op1 - op5; option text
// quick call for OpenNewQuestion() with player color settings
/////////////////////////////////////////////////////////////////////////////////
func QuestMessage1(options,default,text,op1,op2,op3,op4,op5,op6)
{
return OpenNewQuestion(text,options,COLOR_WHITE,COLOR_GREEN,default,op1,op2,op3,op4,op5,op6);
}
func QuestMessage2(options,default,text,op1,op2,op3,op4,op5,op6)
{
return OpenNewQuestion(text,options,COLOR_WHITE,COLOR_MAGENTA,default,op1,op2,op3,op4,op5,op6);
}

/////////////////////////////////////////////////////////////////////////////////
// IN: str; text; question text
// IN: int; options; number of answer options
// IN: str; textcol; question text colour
// IN: str; bordcol; question border colour
// IN: int; default=0; default selected answer
// [IN]: str; op1 - op5; option text
// OUT: int; selected answer
// Opens a question dialog.
// Uses DialogNewQuestion() function for dialog creation.
/////////////////////////////////////////////////////////////////////////////////
func OpenNewQuestion(text,options,textcol,bordcol,default,op1,op2,op3,op4,op5,op6)
{
GamePause(1);
if(!?default) default=0;
g_dlgquestion_text = text;
g_op1 = op1;
g_op2 = op2;
g_op3 = op3;
g_op4 = op4;
g_op5 = op5;
g_op6 = op6;
g_opt = options;

select = RunDialogSelect( gs_fid("DialogNewQuestion"), options, default, true );
GamePause(0);
return select;
}

/////////////////////////////////////////////////////////////////////////////////
// IN: int; select; current selection index
// New Question creation function used by NewQuestion().
/////////////////////////////////////////////////////////////////////////////////
func DialogNewQuestion( select )
{
text = "{a:center}"+g_dlgquestion_text+"nn{c:0xff0000}";
if(g_opt==1)
{
if(select==0) text += "{f:1}"+g_op1;
}
if(g_opt==2)
{
if(select==0) text += "{f:1}"+g_op1+"{f:0}n"+g_op2;
if(select==1) text += g_op1+"n{f:1}"+g_op2+"{f:0}";
}
else if(g_opt==3)
{
if(select==0) text += "{f:1}"+g_op1+"{f:0}n"+g_op2+"n"+g_op3;
if(select==1) text += g_op1+"n{f:1}"+g_op2+"{f:0}n"+g_op3;
if(select==2) text += g_op1+"n"+g_op2+"n{f:1}"+g_op3+"{f:0}";
}
else if(g_opt==4)
{
if(select==0) text += "{f:1}"+g_op1+"{f:0}n"+g_op2+"n"+g_op3+"n"+g_op4;
if(select==1) text += g_op1+"n{f:1}"+g_op2+"{f:0}n"+g_op3+"n"+g_op4;
if(select==2) text += g_op1+"n"+g_op2+"n{f:1}"+g_op3+"{f:0}n"+g_op4;
if(select==3) text += g_op1+"n"+g_op2+"n"+g_op3+"n{f:1}"+g_op4+"{f:0}";
}
else if(g_opt==5)
{
if(select==0) text += "{f:1}"+g_op1+"{f:0}n"+g_op2+"n"+g_op3+"n"+g_op4+"n"+g_op5;
if(select==1) text += g_op1+"n{f:1}"+g_op2+"{f:0}n"+g_op3+"n"+g_op4+"n"+g_op5;
if(select==2) text += g_op1+"n"+g_op2+"n{f:1}"+g_op3+"{f:0}n"+g_op4+"n"+g_op5;
if(select==3) text += g_op1+"n"+g_op2+"n"+g_op3+"n{f:1}"+g_op4+"{f:0}n"+g_op5;
if(select==4) text += g_op1+"n"+g_op2+"n"+g_op3+"n"+g_op4+"n{f:1}"+g_op5+"{f:0}";
}
else
{
if(select==0) text += "{f:1}"+g_op1+"{f:0}n"+g_op2+"n"+g_op3+"n"+g_op4+"n"+g_op5+"n"+g_op6;
if(select==1) text += g_op1+"n{f:1}"+g_op2+"{f:0}n"+g_op3+"n"+g_op4+"n"+g_op5+"n"+g_op6;
if(select==2) text += g_op1+"n"+g_op2+"n{f:1}"+g_op3+"{f:0}n"+g_op4+"n"+g_op5+"n"+g_op6;
if(select==3) text += g_op1+"n"+g_op2+"n"+g_op3+"n{f:1}"+g_op4+"{f:0}n"+g_op5+"n"+g_op6;
if(select==4) text += g_op1+"n"+g_op2+"n"+g_op3+"n"+g_op4+"n{f:1}"+g_op5+"{f:0}"+"n"+g_op6;
if(select==5) text += g_op1+"n"+g_op2+"n"+g_op3+"n"+g_op4+"n"+g_op5+"n{f:1}"+g_op6+"{f:0}";
}

DialogPush();
DialogSetText(text);
DialogSetColor(COLOR_DIALOG);
DialogFitCenter();
}

The above code does the 'heavy lifting' of actually running the question functions and sorting it all out - dealing with all the options, and removing a question from that particular selection once it has been 'asked'.

In game.gs:

func Get_Questions()
{
questtab = tab(10);
//answertab = tab(5);
actiontab = tab(10);

qx=1;

if(ObjGet(ObjFind(1001),O_DISABLE)==1) { questtab[qx] = "Question 1";actiontab[qx]=44001;qx=qx+1; }
if(ObjGet(ObjFind(1002),O_DISABLE)==1) { questtab[qx] = "Question 2";actiontab[qx]=44002;qx=qx+1; }
if(ObjGet(ObjFind(1003),O_DISABLE)==1) { questtab[qx] = "Question 3";actiontab[qx]=44003;qx=qx+1; }
if(ObjGet(ObjFind(1004),O_DISABLE)==1) { questtab[qx] = "Question 4";actiontab[qx]=44004;qx=qx+1; }
if(ObjGet(ObjFind(1005),O_DISABLE)==1) { questtab[qx] = "Question 5";actiontab[qx]=44005;qx=qx+1; }

questtab[qx] = "ASK NOTHING";actiontab[qx]=0;qx=qx+1;

totquest = qx-1;
}

func ActionObject_1000()
{
Get_Questions();

idx = ObjFind(1000);
if(ObjGet(idx,O_STATUS)==0 && totquest>1)
{
choice = QuestMessage1(totquest,0,"Choose a question",questtab[1],questtab[2],questtab[3],questtab[4],questtab[5],questtab[6]);

if(choice==0) { Get_Answer(actiontab[1]); }
if(choice==1) { Get_Answer(actiontab[2]); }
if(choice==2) { Get_Answer(actiontab[3]); }
if(choice==3) { Get_Answer(actiontab[4]); }
if(choice==4) { Get_Answer(actiontab[5]); }
if(choice==5) { Get_Answer(actiontab[6]); }
}
}

func Get_Answer(ans)
{
if(ans==44001) ObjSet(ObjFind(1001),O_DISABLE,0);
if(ans==44002) ObjSet(ObjFind(1002),O_DISABLE,0);
if(ans==44003) ObjSet(ObjFind(1003),O_DISABLE,0);
if(ans==44004) ObjSet(ObjFind(1004),O_DISABLE,0);
if(ans==44005) ObjSet(ObjFind(1005),O_DISABLE,0);
}

This code is the 'front-facing' code, which you'll use and modify for your own purposes. I've noticed that it doesn't seem to be completely finished, as the first function uses a generic name, whereas you're likely to need multiple copies of it in the game, if you want to ask different characters different questions. The last function can happily contain all the actions etc for every option in every question - obviously you need to give them all different identifying numbers though! (for example, in the code above, I've used answer numbers 44001 to 44005. The next question would use 44006, 44007 etc etc.

In the map, I had 6 objects, numbered from 1000 to 1005. The above code checked if they were disabled, and if not, enabled the corresponding option in the question.

Basically, the upshot of it all is that if you action object 1000, it will ask you to select one of 5 options ('questions to ask', as this was meant to be for a murder-mystery game). Once you select an option, the corresponding action happens. I think I was also going to add an 'answer' function too, but can't remember why I didn't. It could be that I decided it wasn't needed.

The really clever bit is that once you have asked, say, question 2, the game then removes question 2 from the list when you next action that object. Previously, if you'd wanted to ask a list of questions, you'd have had to code a new dialog for each possible combination of questions - which obviously would be ludicrous. With this code, the function DialogNewQuestion handles all that.

Plus, you can add more than 5 questions into each character's code, as long as the variables only allow 5 to be displayed at once. So for example, once question 2 has been asked, a new question, question 6, can be added to that character's questions, simply by defining the if statements correctly.

Anyway, have a play around with it. To me, it opens up a lot of possibilities - I was intending to use it to write a mystery game, where you had to go around interrogating characters, finding out different information and causing different things to happen, depending on what questions you asked them. I never got round to it though, and probably never will.

It should all work as is; I don't think I've missed anything. There's a line of code '#def O_EXAMINE 32' in gamedef.gs, but I can't see anywhere that I've used it, so I'm thinking it was just a hang-over from an early version of the code.

Once you've had a play, if you still have any questions, please ask and I'll do my best to answer, when I'm next on here!

👍 0
#81754
wow that's awesome. I may have to use that to replace some of the question stuff I had done for my current Dizzy project.
👍 0
#81843

A plea for help! This problem has been annoying me something fierce for months now. I've tried everything I can think of so I'll leave it here and see what you guys think. Even if you can't solve it I'm interested to hear how you MIGHT go about solving it!

Okay. The map is open, all characters and objects are reachable and can be interacted with or used in ANY order.

Grand Dizzy needs a newspaper and some spectacles. Denzil needs a screwdriver for which he'll give you the spectacles. Dylan gives you the newspaper after you've spoken to him.

Now this is where it gets complicated: grand dizzy says something when you first encounter him but doesn't speak again until you give him one of the two objects, and each dialogue is unique for whatever object he's given. Denzil asks for the screwdriver but displays a certain message depending on whether Dylan has given you the newspaper or not and won't give you the spectacles until you have taken the newspaper. Once the spectacles and the newspaper have been taken Dylan and Denzil both say something else. Finally Grand Dizzy will, as previously mentioned, have different dialogue for each object but say something else after being given both!

I hope that made sense and I'd love to hear your thoughts, musings or general reactions to it! :smile:

👍 0
#81845
I must have something to do with the status updates?
👍 0
#81846

[quote data-userid="55" data-postid="81845"]

I must have something to do with the status updates?

[/quote]

That's what I thought too Meph, but I can't figure out how to get it working when there's so many things going on :sad:

👍 0
#81848

Have you thought about adding an extra invisible non actionable dynamic object that acts as a check for updating the status of all characters.

for example let's say you add dynamic object 2000 to the map (material air, draw mat, class none) and use this as a check when giving Gdizzy the objects. That way you only change the status of GDizzy to having both articles and can be included in the 'UseObject' function for Gdizzy:

func UseObject_200(idx) //Gdizzy
{
if (idx == ObjFind(400)) //specs
{
InventorySub(idx);
GDizzy's message on getting specs

idx = ObjFind(2000);
ObjSet(idx, O_STATUS, ObjGet(idx, O_STATUS) +1);
if (ObjGet(idx, O_STATUS) == 2)
{

Update status of Gdizzy to having got both items
Add message here if speaks after getting both items
Change status of Dylan and Denzil if required

return;
}
return;
}
if (idx == ObjFind(401)) //paper
{
InventorySub(idx);


GDizzy's message on getting paper

idx = ObjFind(2000);
ObjSet(idx, O_STATUS, ObjGet(idx, O_STATUS) +1);
if (ObjGet(idx, O_STATUS) == 2)
{


Update status of Gdizzy to having got both items
Add message here if speaks after getting both items
Change status of Dylan & Denzil if required

return;
}
return;
}
else
{
DropObject(idx);
}
}

I know you have to add the same bit of code for each needed item, but it's not a lot of code and saves mucking about trying to change Gdizzy's status after getting each needed item.

Not sure whether you mean that Denzil won't give the glasses unless Dizzy is carrying the paper or has just picked it up before and dropped it again. If the first, then just add '&& InventoryHasItem(401)' to the actioning of Denzil to get the specs. Otherwise you can make the paper initially an actionable object and change it's status to 1 when Dizzy first picks it up then use '&&

ObjGet(ObjFind(401), O_STATUS) == 1) as a check:
func ActionObject_401()
{
idx = InventoryCount();
if (idx >2)
{
OpenDialolgMessage("YOUR HANDSnARE FULL");
return;
}
idx = ObjFind(401);
ObjSet(idx, O_CLASS, 4);
ObjPresent(idx);
PickupObject(idx);
ObjSet(idx, O_STATUS, 1);
}

I've used an InventoryCheck first otherwise the engine will change the status to 1 if dizzy is already carrying 3 items.

Hope this lot makes sense.

👍 0
#81853
Thanks Grandad!! It looks like that might be useful (certainly not anything I've previously tried.) I'll give it a go and let you know how I get on.

Whilst I'm here I've a general question: In my (limited) experience when the player touches a collider, the object or whatever is triggered and the function continues to its end. But can a collider be made to trigger something ONLY when a player is touching it but then reset if they step away?
👍 0
#81854

Yes, but it can be quite a lot of coding depending on what you are trying to achieve. I've only used it for when Dizzy is standing still within the collider to activate something and deactivate it when he's not standing still. In the following example, the collider activates say a spider going up and down, 'cos in an UpdateTrain function the object has to have a status of 1:

func CollideObject_200_2() // mode 2 is 'continuing'
{
if (PlayerGet(P_TILE) == 10) //dizzy idle
{
ObjSet(ObjFind(201), O_STATUS, 1);
}
if (PlayerGet(P_TILE) != 10)
{
ObjSet(ObjFind(201), O_STATUS, 0);
}
}

func UpdateRoom_10_10()
{
idx = ObjFind(201);
AIUpdateTrain(idx);
}

So, when Dizzy is standing still within the collider the spider moves up and down and as soon as he moves, the spider stops moving (but is still visible). That way you can just leave the collider active. Note, you don't have to include 'return' as it only works when Dizzy is within the boundaries of the collider.

If the collide is activating something that strarts from a certain position and deactivation takes it back to it's start position you have to reset the object's x & y axis and target (if an AI function) and possibly disable it too, depending on what you are doing.

However, if you want the collider to activate no matter what Dizzy is doing, then you'll have to include all the possible tiles that Dizzy 'uses and if you've included a scuba in the game then that's an awful lot of extra coding to take into consideration (don't forget that || = 'or').

Hope this is useful.

👍 0